Порядок вызовов конструктора для вашей иерархии наследования будет:
Base()
DerivedBaseTwo()
Base()
DerivedBaseOne()
Derived()
Порядок действительно хорошо определен и зависит от порядка, в котором вы упоминаете деривацию для базовых классов, и порядка, в которомВы объявляете участников в классе для участников.(См. Ссылку на стандарт C ++ ниже.)
Дважды вызывается конструктор Base ()?
ДА
Конструктор класса Base()
вызывается здесь дважды, потому что два класса DerivedBaseTwo()
и DerivedBaseOne()
являются производными от него, поэтому конструктор базового класса вызывается один раз для каждого из них.Ваш Derived
класс имеет два отдельных Base
подобъекта по нескольким путям (от одного до DerivedBaseOne()
, а другой через DerivedBaseTwo()
).
Иерархия классов с множественным наследованием необычна и приводит кк проблеме, называемой Проблема наследования в форме ромба .Чтобы избежать этой проблемы, C ++ вводит понятие Виртуальный базовый класс .
Ссылка:
C ++ 03 Standard: 12.6.2 / 5, Инициализация баз и членов
Инициализация должна выполняться в следующем порядке:
- Сначала и только для конструктора самого производного классакак описано ниже, виртуальные базовые классы должны быть инициализированы в том порядке, в котором они появляются при обходе слева направо по глубине направленного ациклического графа базовых классов, где «слева направо» - порядок появленияИмена базовых классов в производном списке базовых спецификаторов.
- Затем прямые базовые классы должны быть инициализированы в порядке объявления, как они появляются в списке базовых спецификаторов (независимо от порядка записи в памяти).инициализаторы).
- Затем нестатические элементы данных должны быть инициализированы в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-initializers).
- Наконец, выполняется тело конструктора.