Каков порядок вызова деструкторов и конструкторов на C++? Используя примеры некоторых базовых классов и производных классовКаков порядок, в котором деструкторы и конструкторы вызываются в C++
ответ
Заказ:
- Базовый конструктор
- производный конструктор
- производный деструктор
- Base деструктор
Пример:
class B
{
public:
B()
{
cout<<"Construct B"<<endl;
}
virtual ~B()
{
cout<<"Destruct B"<<endl;
}
};
class D : public B
{
public:
D()
{
cout<<"Construct D"<<endl;
}
virtual ~D()
{
cout<<"Destruct D"<<endl;
}
};
int main(int argc, char **argv)
{
D d;
return 0;
}
Выход Например:
Построить Б
Построить D
Destruct D
Destruct Б
Несколько уровней наследования работает как стек:
Если вы считаете, толкая элемент в стек, как строительство, и принимая его как разрушение, то вы можете посмотреть на несколько уровней наследования, как стек.
Это работает для любого количества уровней.
Пример D2 происходит из D происходит из B.
Push-B на стеке, нажмите D на стеке, нажмите D2 в стеке. Таким образом, порядок построения - B, D, D2. Затем, чтобы узнать, как начинается порядок уничтожения. D2, D, B
Более сложные примеры:
Для более сложных примеров, смотрите ссылку предоставленную @JaredPar
Подробное описание этих событий, в том числе и виртуального множественного наследования доступен на C++ FAQ Lite. Раздел 25,14 и 25,15
https://isocpp.org/wiki/faq/multiple-inheritance#mi-vi-ctor-order
Предоставлено ссылка мертва , – jbx
Теперь ссылка работает хорошо. –
Кроме того, имейте в виду, что в то время как элементы массива строится первый -> Наконец, они разрушаются в обратном порядке: последний -> первый.
+1 Это верно для всего, что угодно. Орден разрушения всегда является противоположностью конструкции. Статические переменные не имеют гарантированного порядка построения, но разрушение произойдет в обратном порядке. –
Это (ожидаемое) поведение шаблонизированного контейнера и/или встроенное 'new []'/'delete []' поведение? – franji1
я должен добавить к предыдущим ответам, потому что все, кажется, игнорируя его
Когда у вас есть полученных экземпляра класса является созданным, это правда, что код внутри конструктора база будет называться перед тем Кодекса внутри конструктор из получено, но имейте в виду, что производном еще технически «создал»перед тембаза.
И когда у вас есть производный класса деструктор который вызывается, это правда, что код внутри производный деструктор перед тем код внутри базовый деструктор, но и сохранить в виду, что base is уничтоженодо.
Когда я говорю созданный/уничтожил Я на самом деле имея в виду выделяемой/высвобождены.
Если вы посмотрите на макет памяти этих экземпляров, вы увидите, что производный экземпляр составляет базовый экземпляр. Например:
Памяти получено: 0x00001110 до 0x00001120
Памяти базы: 0x00001114 до 0x00001118
Таким образом, производный класс должен быть выделены ПЕРЕД баз в строительстве. И производный класс должен быть освобожден ПОСЛЕ база в уничтожении.
Если у вас есть следующий код:
class Base
{
public:
Base()
{
std::cout << "\n Base created";
}
virtual ~Base()
{
std::cout << "\n Base destroyed";
}
}
class Derived : public Base
{
public:
Derived()
// Derived is allocated here
// then Base constructor is called to allocate base and prepare it
{
std::cout << "\n Derived created";
}
~Derived()
{
std::cout << "\n Derived destroyed";
}
// Base destructor is called here
// then Derived is deallocated
}
Так что, если вы создали Derived d;
и она была выходить за рамки, то вы получите выход в @ ответ Брайана.Но поведение объекта в памяти на самом деле не в том же порядке, это больше похоже на это:
Строительство:
Derived выделено
Base выделено
Базовый конструктор называется
Производственный конструктор под названием
Разрушение:
Derived деструктор называется
База деструктор называется
База высвобождены
Derived высвобождены
Возможно, OP хочет знать о классе D: public A, B, C ... –
Множественное наследование добавляет некоторую сложность: http://www.gotw.ca/gotw/080.htm –