Виртуальный деструктор
Как известно, указатель на базовый класс является указателем и на классы наследники, а также можно создать объект класса (как переменную) в динамической памяти и присвоить адресу указателю на базовый класс.
т.е.
class A {//code};
class B : public A {//code};
int main ()
{
A *ptrA=new B;
delete ptrA;
return 0;
}
Что в этом случае произойдет?
При таком вызове в динамической памяти создается объект класса B, размер которого обычно больше размера класса A (т.к. класс A входит в класс B).
При таком вызове указатель *ptpA содержит указатель на часть класса B которая соответствует A., следовательно при вызове оператора delete *ptrA; удалится лишь «подкласс A» входящий в класс B, в этом случае вызовется деструктор класса A, а часть соответствующая классу B так и останется в динамической памяти, а мы получим утечку.
Можно сказать, что указатель *ptpA ничего не знает о классе B.
Чтобы этого избежать нужно применить деструктор сделать виртуальным:
class A
{
public:
A(){}
virtual ~A(){}
//code
};
class B : public A
{
public:
B(){}
~B() override {}
//code
};
В этом случае в коде A *ptpA=new B будет подставлен адрес виртуального деструктора (т.е. деструктор класса B), и после вызова деструктора (удаления) класса B будет вызван деструктор класса A.
Чисто виртуальный деструктор:
Аналогично абстрактным классам с чисто виртуальными методами можно создать чисто виртуальный деструктор, общая идея примерно такая же, синтаксис приведен ниже.
class A
{
public:
A(){}
virtual ~A() =0;
//code
};
A:: A(){}; //ВАЖНО сделать внешнюю пустую функцию
На мой взгляд чисто виртуальный деструктор может иметь смысл, если в каждом классе наследнике будет по-своему (в разном объеме) выделяться память.