2016-05-07 5 views
2

У меня есть этот C++ код:Объясните порядок конструктора/деструктора вызовов в этом C++ код

class BaseClass { 
    int id; 
public: 
    BaseClass() { printf("BaseClass()\n"); } 
    virtual ~BaseClass() { printf("~BaseClass()\n"); } 
}; 

class Class1 : public BaseClass 
{ 
    int id; 
public: 
    Class1() { printf("Class1()\n"); } 
    ~Class1() { printf("~Class1()\n"); } 
}; 

class Class2 : public Class1 
{ 
    BaseClass id; 
public: 
    Class2() { printf("Class2()\n"); } 
    ~Class2() { printf("~Class2()\n"); } 
}; 

class Class3 : virtual public BaseClass 
{ 
    int id; 
public: 
    Class3() { printf("Class3()\n"); } 
    ~Class3() { printf("~Class3()\n"); } 
}; 

class Class4 : public Class3, virtual public Class1 
{ 
    Class3 id; 
public: 
    Class4() { printf("Class4()\n"); } 
    ~Class4() { printf("~Class4()\n"); } 
}; 

int main(int argc, char* argv[]) 
{ 
    BaseClass *p = new Class2; 
    Class2 *p1 = new Class2; 
    Class3 *p2 = new Class3; 
    delete p; 
    delete p1; 
    delete p2; 
    return 0; 
} 

Это выход:

BaseClass() 
Class1() 
BaseClass() 
Class2() 
BaseClass() 
Class1() 
BaseClass() 
Class2() 
BaseClass() 
Class3() 
~Class2() 
~BaseClass() 
~Class1() 
~BaseClass() 
~Class2() 
~BaseClass() 
~Class1() 
~BaseClass() 
~Class3() 
~BaseClass() 

, и я не понимаю, почему. Я хотел бы ожидать, что выход состоит в следующем:

BaseClass() 
Class1() 
Class2() 
BaseClass() 
Class1() 
Class2() 
... 

т.д.

Почему не Class2() печатается после Class1() при создании, например, p1? Связано ли это с виртуальным наследованием?

+0

Когда класс А наследует класс B, построение класса B требует класса А будет построен первый - как строительство B может потребовать использования –

+0

@songyuanyao я случайно оставил из первая строка при копировании вывода, извините за это. – Eutherpy

ответ

2

Давайте идти шаг за шагом с первым объектом строятся:

new Class2; 

Это первый объект, вы contructing, давайте назвал его p.

BaseClass() 

p «s BaseClass.

Class1() 

p «s Class1, подкласс BaseClass получает построен.

BaseClass() 

Это id членом Class2 строится.

Class2() 

И теперь, наконец, Class2, p сам.

Итак, несмотря на вашу веру, Class2() печатается после Class1(). Кроме того, что вы забыли, что Class2 также имеет член id, это BaseClass и который также должен быть сконструирован до того, как вызывается конструктор Class2::Class2(). Вы считали, что вы видите второй объект BaseClass ed объекта, который был сконструирован, но то, что действительно создавалось, было объектным объектом BaseClass.

P.S. Это C++. В C++ используется std::cout вместо printf(). printf() - так ... прошлый век.

+0

Конечно ... Я полностью проигнорировал это, даже не заметил, что 'id' не является целым числом, как в« BaseClass »и« Class1 ». Такая хромая ошибка :) Кстати, это не мой код. :) – Eutherpy

3

Почему Class 2() не печатается после Class1() при создании, например, p1?

Поскольку Class2 имеет не статический объект члена с типом BaseClass, его т е р будет называться перед CTOR из Class2.

Согласно initialization order:

инициализации порядка

1) Если конструктор для наиболее производного класса, виртуальные базовой классов инициализируются в том порядке, в котором они появляются в глубине - первый слева-направо обход объявлений базового класса (слева направо относится к виду в списках базового спецификатора)

2) Тогда прямые базовые классы - это i nitialized в левой направо порядке, как они появляются в списке базовых спецификатора этого класса

3) Затем, не статические данные инициализируются в порядке декларации в определении класса.

4) И, наконец, тело конструктора выполняется

Для new Class2;, прямой базовый класс Class1 и его базовый класс BaseClass будет вызван в первую очередь. Затем будет вызываться нестатический элемент данных id с типом BaseClass. И тело ctor Class2 будет вызываться наконец. Таким образом, вы получите

BaseClass() 
Class1() 
BaseClass() 
Class2()