#cpp #наследование #language_lawyer #неопределенное_поведение
Как известно, при необходимости удаления через указатель на родительский класс, класс должен иметь виртуальный деструктор, чтобы оператор delete вызвал верный деструктор дочернего класса. Но что если лично мне вообще не нужен деструктор ни в одном из классов? Являются ли автоматически сгенерированные деструкторы взаимозаменяемыми? Или я всё равно обязан добавить виртуальный деструктор в родительский класс? Насколько я понимаю, генерируется пустой деструктор, поэтому при уничтожении объекта ничего происходить не будет. Да и вообще, компилятор умный и вызов пустой функции выкинет, соответственно, никакой деструктор при удалении вызываться не будет. В таком случае кажется странным необходимость добавлять виртуальную функцию, которая будет вызываться, если эта функция заведомо является nopом. https://ideone.com/8ldKsU struct A { int x; A(unsigned x) : x(x) {} }; struct B : A { B() : A(7) {} }; int main() { A *a = new B(); delete a; return 0; }
Ответы
Ответ 1
Ответ на этот вопрос по сути совпадает с этим ответом. Виртуальным деструктор может стать только при наследовании или явном указании, больше никак. Компилятор генерирует деструктор, который должен удалить все объекты, т.е. «пустой» это не верно в общем случае. В стандарте нет исключений для этого случая, код в вопросе даёт неопределённое поведение согласно стандарту. Дополнительно, пустой с точки зрения исходного кода деструктор на деле не является пустым, в него вкладывается логика по деаллокации экземпляра класса. Поэтому деструкторы разных классов по сути являются разными, не взаимозаменяемыми.Ответ 2
Как известно, при необходимости удаления через указатель на родительский класс, класс должен иметь виртуальный деструктор, чтобы оператор delete вызвал верный деструктор дочернего класса. Если дело дошло до виртуальных функций и до удаления объекта по указателю на базовый класс, то рекомендуется писать виртуальные деструкторы, хотя бы и пустые. Потом меньше возни будет их добавлять. Опять же любая программа имеет тенденцию стать библиотекой и в таком качестве следующие пользователи начинают производить свои классы от Ваших классов. Тут и пригодится виртуальный деструктор. Что касается приведенного примера, то в нем нет ни виртуальных функций, ни НЕОБХОДИМОСТИ удалять объект класса по по указателю на базовый класс. В качестве иллюстрации того, что в С++ МОЖНО обойтись и без виртуальных деструкторов такой пример имеет право на существование. Но в реальном коде с более-менее развитой системой иерархии классов виртуальные деструкторы must have.
Комментариев нет:
Отправить комментарий