Виртуальный деструктор нужен всегда, когда класс предполагается использовать в качестве базового и поддерживает полиморфизм (наследование и динамическое связывание).
🚩Зачем нужен виртуальный деструктор?
Если у базового класса деструктор не виртуальный, а удаление происходит через указатель на базовый класс, деструктор производного класса не вызовется! Это приведёт к утечке памяти или некорректному освобождению ресурсов.
Пример проблемы без виртуального деструктора
#include <iostream>
class Base {
public:
~Base() { std::cout << "Деструктор Base\n"; } // НЕ виртуальный!
};
class Derived : public Base {
public:
~Derived() { std::cout << "Деструктор Derived\n"; }
};
int main() {
Base* obj = new Derived();
delete obj; // Проблема! Деструктор Derived НЕ вызывается!
}
Вывод
Деструктор Base
🚩Решение: сделать деструктор виртуальным
Если объявить деструктор базового класса виртуальным (
virtual), то при удалении через указатель на базовый класс будет вызван полный цепной деструктор. Используем virtualclass Base {
public:
virtual ~Base() { std::cout << "Деструктор Base\n"; } // Виртуальный!
};
class Derived : public Base {
public:
~Derived() { std::cout << "Деструктор Derived\n"; }
};
int main() {
Base* obj = new Derived();
delete obj; // Теперь вызываются оба деструктора
}Вывод
Деструктор Derived
Деструктор Base
🚩Когда не нужно делать деструктор виртуальным?
Когда класс не предназначен для наследования
Например,
std::vector, std::string, std::unique_ptr – у них нет виртуального деструктора, так как они не предполагают полиморфное использованиеКогда удаление всегда происходит по ссылке/указателю на сам класс, а не на базовый
Derived* obj = new Derived();
delete obj; // В любом случае вызовет правильный деструктор
Если класс "заморожен" (
final) class FinalClass final {
public:
~FinalClass() { std::cout << "Деструктор\n"; }
};Ставь 👍 и забирай 📚 Базу знаний