2010-10-02 3 views
1
#include <iostream> 
class A 
{ 
public: 
    A() { std::cout << " A ctor" << std::endl; } 
    A(int i) { std::cout << " A ctor i" << std::endl; } 
    ~A() { std::cout << " A dtor" << std::endl; } 
}; 
class B: public A 
{ 
public: 
    B() : A() { std::cout << " B ctor" << std::endl; } 
    ~B() { std::cout << " B dtor" << std::endl; } 
}; 
class C: public A 
{ 
public: 
    B _b; 

    C() : _b(), A() { std::cout << " C ctor" << std::endl; } 
    ~C() { std::cout << " C dtor" << std::endl; } 
}; 
int main() 
{ 
    C c; 
} 

Выход:Конструкторы заказ

A ctor 
A ctor 
B ctor 
C ctor 
C dtor 
B dtor 
A dtor 
A dtor 

Что такое порядок инициализации. список? Почему, в init. список C, ctor A, названный до ctor B? Я думал, что выход должен быть:

A ctor 
B ctor 
A ctor 
C ctor 
C dtor 
A dtor 
B dtor 
A dtor 

Спасибо.

+0

Вы показываете код на C++, но указываете как C#. Не могли бы вы прояснить? –

+0

Я перемаркировал его, очевидно, не C# – CyberDude

+1

Не является ли последовательность конструкторов 'A, A, D, A, B, C'? Трудно поверить, что конструктор для члена '_d' не вызывается. –

ответ

4

Порядок, в котором вы пишете инициализацию в списке инициализации не важно, порядок инициализации определяется независимо от этого списка по другим правилам:

  • Первый базовый класс инициализируется. Вот почему при построении C сначала вызывается конструктор базового класса A. Все, что принадлежит базовому классу, построено на этом шаге (базовые классы и переменные-члены, принадлежащие базовому классу), так же, как если бы был создан нормальный объект этого базового класса.
  • Затем переменные-члены производного класса инициализируются в порядке , в котором они объявлены в классе. Поэтому, если имеется несколько переменных-членов, порядок, в котором они объявлены, определяет порядок, в котором они инициализированы. Порядок списка инициализации не имеет значения.
+0

И для завершения: для создания 'C' вы сначала создаете' A' (его базовый класс), который выводит 'ctor A', затем' B' (его член), который выдает 'ctor A' и' ctor B' (в этом порядке) и, наконец, выполнить тело конструктора C, которое выдает 'ctor C', давая' AABC'. –

+1

На самом деле некоторые компиляторы (gcc, для одного) будут предупреждать вас о порядке списка инициализации, который отличается от порядка объявления. –

2

Конструкторы базового класса вызывается перед конструкторами производных классов. Это позволяет производному классу использовать члены в базовом классе во время их построения.

Во время разрушения действует обратное. Уничтожение подкласса происходит до базового класса по той же причине.

Если вы думаете об этом - это имеет смысл. Базовый класс не знает этого подкласса, но противоположное не соответствует действительности. Это определяет порядок, чтобы все работало, как ожидалось.

+0

Каков был порядок, если B не был производным классом A? – Sanich

+0

@ Санич: В инициализации будет меньше А, а в уничтожении будет меньше А. В противном случае порядок будет таким же. –

+0

@Reed Copsey: Верно ли, что если B не был производным классом A, oredr of ctors был бы: A, B, C или он был бы: B, A, C? – Sanich

0

Я думаю, что ваше замешательство - это то, что список инициализации C обрабатывается справа налево, а не слева. Это связано с тем, что компилятор обрабатывает параметры в режиме «последний в первый раз». Следовательно, порядок: Первый А'тор. Так как _b является объектом B, который является производным от A, базовый класс строится до производного класса, поэтому A c'tor вызывается, а затем B'c'tor. И, наконец, называется C'tor. Когда объект C разрушен, он следует в обратном порядке.

0

Если вы используете компилятор GNU, вам поможет вариант -Wall.

Смежные вопросы