Правила программирования на С и С++. Главы 7-8 - Деструкторы всегда должны быть виртуальными
ОГЛАВЛЕНИЕ
Страница 52 из 74
139. Деструкторы всегда должны быть виртуальными.
Рассмотрим этот код:
class base{
char *p;~base() { p = new char[SOME_SIZE]; }
base() { delete p; }
};class derived : public base
{
char *dp;~derived() { dp = new char[[SOME_SIZE]; }
derived() { delete dp; }
};Теперь рассмотрим этот вызов: base *p = new derived;// ...
delete p;
Запомните, что компилятор не знает, что p на самом деле указывает на объект производного класса. Он исходит из того, что p указывает на объявленный тип base. Следовательно, delete p в действительности превращается в: _base__destructor(p);free(p);
Деструктор производного класса никогда не вызывается. Если вы переопределите эти классы, сделав этот деструктор виртуальным: virtual ~base() { /* ... */ }то компилятор получит доступ к нему при помощи таблицы виртуальных функций, просто как к любой другой виртуальной функции. Так как деструктор теперь виртуальный, то delete p превращается в: ( p->_vtable[DESTRUCTOR_SLOT] ) (p);Так как p указывает на объект производного класса, то вы получаете деструктор производного класса, который вызывается за деструктором базового класса, когда выполнены компоненты производного класса.