Возник вопрос насчет виртуального деструктора.
Насколько я понял - виртуальный деструктор нужен, чтобы в наследованном классе, который у нас есть (от базового) можно было вызвать (прямо оттуда) деструктор базового, а т.к. простой деструктор наследованный класс не понимает, то нужно создавать виртуальный.
И все это чтобы не было никакой утечки памяти.
Так ли я понял суть?
Ответ
Не, немного не так. Деструктор базового класса из деструктора производного вызывать не надо (да и нельзя), он сам вызовется автоматически. Проблема в другом: деструктор производного класса может быть не вызван!
Представьте себе такую ситуацию:
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 деструкторов нету вовсе.
Комментариев нет:
Отправить комментарий