ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 11) онлайн

Виртуальные деструкторы

Знаете ли вы, что деструкторы базового класса обязательно должны быть вирту-

альными? Допустим, чтобы удалить объект порожденного класса, вы выполнили

delete над указателем базового класса, указывающим на порожденный класс.

Если деструктор базового класса не является виртуальным, тогда delete, будучи

обычным методом, вызовет деструктор для базового класса вместо того, чтобы

запустить деструктор для порожденного класса. Это приведет к тому, что будет

удалена только та часть объекта, которая относится к базовому классу. Програм-

ма VIRTDEST демонстрирует это.

Листинг 11.6. Программа VIRTDEST

//vertdest.cpp

//Тест невиртуальных и виртуальных деструкторов

#include <iostream>

using namespace std;

///////////////////////////////////////////////////////////

class Base

   {

   public:

      ~Base()                 //невиртуальный деструктор

//    virtual ~Base()         //виртуальный деструктор

         { cout << "Base удален\n"; }

   };

///////////////////////////////////////////////////////////

class Derv : public Base

  {

   public:

      ~Derv()

         { cout << "Derv удален\n"; }

   };

///////////////////////////////////////////////////////////

int main()

{

   Base* pBase = new Derv;

   delete pBase;

   return 0;

}

 

Программа выдает такой результат:

Base удален

Это говорит о том, что деструктор для Derv не вызывается вообще! К такому

результату привело то, что деструктор базового класса в приведенном листинге

невиртуальный. Исправить это можно, закомментировав первую строчку опре-

деления деструктора и активизировав вторую. Теперь результатом работы про-

граммы является:

Derv удален

Base удален

 

Только теперь обе части объекта порожденного класса удалены корректно.

Конечно, если ни один из деструкторов ничего особенно важного не делает (на-

пример, просто освобождает память, занятую с помощью new), тогда их вирту-

альность перестает быть такой уж необходимой. Но в общем случае, чтобы быть

уверенным в том, что объекты порожденных классов удаляются так, как нужно,

следует всегда делать деструкторы в базовых классах виртуальными.

Большинство библиотек классов имеют базовый класс, в котором есть вир-

туальный деструктор, что гарантирует нам наличие виртуальных деструкторов в

порожденных классах.

 

10