Почему деструктор базового класса вызывается для производного объекта, если деструктор производного класса не виртуален?
Почему все деструкторы, ~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;
}
3 ответа
Однажды 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 через указатель типа A просто вызовет деструктор A. Чтобы обеспечить вызов деструктора B в этом случае, мы должны указать деструктор A как виртуальный:
virtual ~A();
Как сказал @juanchopanza - объявление базового деструктора виртуальным означает, что у всех потомков есть виртуальные деструкторы. Эта унаследованная виртуальность одинакова для любых методов, а не только для деструкторов.
Вот почему я взял интервью у людей, которые не знали, что делает ключевое слово, потому что им когда-либо приходилось переопределять методы, полученные из фреймворка, поэтому все они были виртуальными (вздох).