Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда следует объявлять деструктор виртуальным?
Краткий ответ
Деструктор должен быть виртуальным в базовом классе, если он используется для наследования и объекты удаляются через указатель на базовый класс.
Почему это критично?
Без виртуального деструктора происходит утечка памяти. Удаляя объект производного класса через указатель на базовый класс без virtual, вызывается только деструктор базового класса, а деструктор производного класса не вызывается.
Пример проблемы
class Base {
public:
~Base() { cout << "Base деструктор\\n"; }
};
class Derived : public Base {
public:
int* data;
Derived() : data(new int[1000]) {}
~Derived() {
cout << "Derived деструктор\\n";
delete[] data; // НЕ вызовется!
}
};
int main() {
Base* ptr = new Derived();
delete ptr; // ПРОБЛЕМА! Только ~Base()
}
Вывод:
Base деструктор
// Derived деструктор НЕ вызван, утечка!
Правильное решение
class Base {
public:
virtual ~Base() { cout << "Base деструктор\\n"; }
};
class Derived : public Base {
public:
int* data;
Derived() : data(new int[1000]) {}
virtual ~Derived() {
cout << "Derived деструктор\\n";
delete[] data;
}
};
int main() {
Base* ptr = new Derived();
delete ptr; // Вызовется ~Derived(), потом ~Base()
}
Вывод:
Derived деструктор
Base деструктор
Правила
1. Базовый класс — деструктор ВСЕГДА virtual
class Shape {
public:
virtual ~Shape() {}
};
class Circle : public Shape {};
2. Если НЕ наследуется — может быть невиртуальным
class FinalClass {
public:
~FinalClass() {} // Невиртуальный — OK
};
class StrictFinal final {
public:
~StrictFinal() {}
};
3. Производные классы — virtual для ясности
class Base {
public:
virtual ~Base() = default;
};
class Derived : public Base {
public:
virtual ~Derived() = default;
};
C++ стиль: = default
class Base {
public:
virtual ~Base() = default;
};
Когда виртуальный деструктор НЕ нужен
- Листовые классы (не наследуются)
- Final классы
- Классы, явно запрещающие наследование
- std::string, std::vector, std::map (не для наследования)
Критически важное замечание
НИКОГДА удалять объект производного класса через базовый указатель без virtual деструктора — это гарантированная утечка памяти и неопределённое поведение.
Похожие вопросы
- Что такое placement new?
- Какой контейнер лежит в основе map?
- Как устроен умный указатель?
- Чем определяется размер указателя?
- Какие знаешь умные указатели в стандартной библиотеке?
- В чем разница между virtual и override?
- Что такое rvalue?
- Как работает реаллокация в vector?
- С какой точностью работает логирование программы
- Приведи пример хеш функции для строки
- Как запретить наследование от класса?
- Для чего нужен explicit конструктор?
- Являются ли сигналы IPC
- Каким вызовом создастся новый поток?
- Что такое инстанцирование шаблона?
- Какая сложность вставки в хеш-таблице?
- Какие объекты можно хранить в std::set?
- Как оператор free понимает, сколько памяти освободить?
- Что такое lseek?
- Что такое std::span?