Если нет виртуального / множественного наследования (что немного усложняет), то правила просты:
- Память объекта выделена
- Конструктор базовых классоввыполняются, заканчивая большинством производных
- Инициализация члена выполняется
- Объект становится истинным экземпляром своего класса
- Код конструктора выполняется
Следует помнить одну важную вещь: до шага 4 объект еще не является экземпляром своего класса, поскольку он получает этот заголовок только после начала выполнения конструктора.Это означает, что если во время конструктора члена выдается исключение, деструктор объекта не выполняется, а только уже созданные части (например, члены или базовые классы) будут уничтожены.Это также означает, что если в конструкторе члена или базового класса вы вызываете любую виртуальную функцию-член объекта, то вызываемая реализация будет базовой, а не производной.Еще одна важная вещь, которую нужно помнить, это то, что член, указанный в списке инициализации, будет построен в том порядке, в котором они объявлены в классе, а НЕ в том порядке, в котором они появляются в списке инициализации (к счастью, большинство приличных компиляторов выдают предупреждение, если вы перечисляете членыв другом порядке по сравнению с объявлением класса).
Обратите также внимание, что даже если во время выполнения кода конструктора объект this
уже получил свой конечный класс (например, в отношении виртуальной диспетчеризации) деструктор классаНЕ будет вызываться, если конструктор не завершит свое выполнение .Только когда конструктор завершает выполнение, экземпляр объекта является настоящим гражданином первого класса среди экземпляров ... до того момента, пока этот пункт является только "желающим экземпляром" (несмотря на наличие правильного класса).
Разрушение происходит вточный обратный порядок: сначала выполняется деструктор объекта, затем он теряет свой класс (т.е. с этого момента объект считается базовым объектом), затем все члены уничтожаются в обратном порядке объявления и, наконец, процесс уничтожения базового класса выполняется досамый абстрактный родитель.Что касается конструктора, если вы вызываете какую-либо виртуальную функцию-член объекта (прямо или косвенно) в базовом или деструкторе-члене, то выполненная реализация будет родительской, поскольку объект потерял свой заголовок класса после завершения деструктора класса.