С++ для начинающих

       

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


В данной функции мы применяем оператор delete:

void doit_and_bedone( vector< Query* > *pvec )

{

   // ...

   for ( ; it != end_it; ++it )

   {

       Query *pq = *it;

       // ...

       delete pq;

   }

}

Чтобы функция выполнялась правильно, применение delete должно вызывать деструктор того класса, на который указывает pq. Следовательно, необходимо объявить деструктор Query виртуальным:

class Query {



public:

   virtual ~Query() { delete _solution; }

   // ...

};

Деструкторы всех производных от Query классов автоматически считаются виртуальными. doit_and_bedone() выполняется правильно.

Поведение деструктора при наследовании таково: сначала вызывается деструктор производного класса, в случае pq – виртуальная функция. По завершении вызывается деструктор непосредственного базового класса – статически. Если деструктор объявлен встроенным, то в точке вызова производится подстановка. Например, если pq указывает на объект класса AndQuery, то

delete pq;

приводит к вызову деструктора класса AndQuery за счет механизма виртуализации. После этого статически вызывается деструктор BinaryObject, а затем – снова статически – деструктор Query.

В следующей иерархии классов

class Query {

public:  // ...

protected:

   virtual ~Query();

   // ...

};

class NotQuery : public Query {

public:

   ~NotQuery();

   // ...

};

уровень доступа к конструктору NotQuery открытый при вызове через объект NotQuery, но защищенный – при вызове через указатель или ссылку на объект Query. Таким образом, виртуальная функция подразумевает уровень доступа того класса, через объект которого вызывается:

int main()

{

   Query *pq = new NotQuery;

   // ошибка: деструктор является защищенным

   delete pq;

}

Эвристическое правило: если в корневом базовом классе иерархии объявлены одна или несколько виртуальных функций, рекомендуем объявлять таковым и деструктор. Однако, в отличие от конструктора базового класса, его деструктор не стоит делать защищенным.



Содержание раздела