Страницы

Поиск по вопросам

вторник, 9 октября 2018 г.

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

Возник вопрос насчет виртуального деструктора.
Насколько я понял - виртуальный деструктор нужен, чтобы в наследованном классе, который у нас есть (от базового) можно было вызвать (прямо оттуда) деструктор базового, а т.к. простой деструктор наследованный класс не понимает, то нужно создавать виртуальный.
И все это чтобы не было никакой утечки памяти.
Так ли я понял суть?


Ответ

Не, немного не так. Деструктор базового класса из деструктора производного вызывать не надо (да и нельзя), он сам вызовется автоматически. Проблема в другом: деструктор производного класса может быть не вызван! Представьте себе такую ситуацию: class Person { ~Person() { } // деструктор не виртуальный };
class Spy : public Person { Gadget* gadgets; public: Spy() { gadgets = new Gadget[10]; } ~Spy() { delete[] gadgets; } };
std::vector citizens; // наполнить значениями for (Person* citizen : citizens) delete citizen; Что случится, если в списке будет один Spy? А вот что: при уничтожении объекта типа Spy по указателю типа Person* вызовется невиртуальный деструктор ~Person. Значит, память под массив gadgets не будет освобождена. Вот вам и утечка памяти. На самом деле, кроме утечки памяти может произойти любая другая неприятность, ведь деструктор, на который вы рассчитывали, не вызовется! Например, может не закрыться файл, и при следующей попытке его открыть программа вылетит. Или не отпустится мьютекс, и при попытке его получить программа зависнет. Ну и ещё куча всяких катастроф может произойти. Хуже того, по стандарту отсутствие виртуального деструктора в данном случае является undefined behaviour, то есть, программа имеет право сделать что угодно: отформатировать винчестер, признаться в любви к вашей химичке через «Вконтакте» или подлить валерьянки в миску с Вискасом. Да, а в C деструкторов нету вовсе.

Комментариев нет:

Отправить комментарий