Правила программирования на С и С++. Главы 7-8
Страница 52. Деструкторы всегда должны быть виртуальными


 

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 указывает на объект производного класса, то вы получаете деструктор производного класса, который вызывается за деструктором базового класса, когда выполнены компоненты производного класса.

 
« Предыдущая статья   Следующая статья »