Правила программирования на С и С++. Главы 7-8 Страница 52. Деструкторы всегда должны быть виртуальными
|
Страница 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 указывает на объект производного класса, то вы получаете деструктор производного класса, который вызывается за деструктором базового класса, когда выполнены компоненты производного класса. |