Почему все деструкторы, ~D()
,~C()
,~B()
,~A()
вызывается в примере ниже?
Существует только один виртуальный деструктор: A
,
Вот код:
#include<iostream>
using namespace std;
class A
{
public:
virtual ~A()
{
cout<<"destruct A\n";
}
};
class B:public A
{
public:
~B()
{
cout<<"destruct B\n";
}
};
class C:public B
{
public:
~C()
{
cout<<"destruct C\n";
}
};
class D:public C
{
public:
~D()
{
cout<<"destruct D\n";
}
};
int main()
{
A* ptr = new D();
delete ptr;
return 0;
}
однажды A
деструктор объявлен virtual
деструкторы всех производных классов также virtual
, даже если они явно не объявлены как таковые .. Таким образом, поведение, которое вы видите, именно то, что ожидается
Порядок уничтожения в производных объектах идет в точности наоборот
порядок построения: сначала деструкторы из наиболее производных
называются классы, а затем деструктор базовых классов.Деструктор может быть определен как виртуальный или даже чисто виртуальный. Ты бы
используйте виртуальный деструктор, если вы ожидаете, что производный класс будет
уничтожается через указатель на базовый класс. Это обеспечит
деструктор самых производных классов будет вызван:
A* b1 = new B;//if A has a virtual destructor
delete b1;//invokes B's destructor and then A's
A* b1 = new B;//if A has no virtual destructor
delete b1;//invokes A's destructor ONLY
Если у A нет виртуального деструктора, удаление b1 через указатель
типа А просто вызовет деструктор А. Для обеспечения призвания
Деструктор B в этом случае мы должны были указать деструктор A как
виртуальная:
virtual ~A();
Как сказал @juanchopanza — объявление базового деструктора виртуальным означает, что у всех потомков есть виртуальные деструкторы. Эта унаследованная виртуальность является то же самое для любых методов, не только деструкторы.
Вот почему я брал интервью у людей, которые не знали, что делает ключевое слово, потому что им когда-либо приходилось переопределять методы, полученные из фреймворка, поэтому все они были виртуальными (вздох).