4

Как известно, при необходимости удаления через указатель на родительский класс, класс должен иметь виртуальный деструктор, чтобы оператор 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;
}
Qwertiy
  • 123,725
  • 1
    дублирование? https://ru.stackoverflow.com/questions/764696/%D0%9C%D0%BE%D0%B6%D0%BD%D0%BE-%D0%BB%D0%B8-%D0%B8%D0%B3%D0%BD%D0%BE%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D0%BF%D1%83%D1%81%D1%82%D0%BE%D0%B3%D0%BE-%D0%BD%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%BA%D0%B0-%D0%BF%D1%80%D0%B8-%D0%BD%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B8-%D0%B4%D0%B5%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D0%BE%D1%80%D0%B0 – Croessmah stands with Russia Dec 29 '17 at 16:16
  • Чем, по Вашему, этот вопрос отличается от предыдущего Вашего вопроса? Ответ на него будет тот же самый. – ixSci Dec 29 '17 at 16:25
  • @ixSci, там есть деструктор. Здесь же в обоих случаях у меня нет моего деструктора - никакого - ни вритуального, ни невиртуального. Компилятор генерирует пустой, насколько я понимаю. Всегда думал, что в таком случае городить виртуальную функцию не надо? – Qwertiy Dec 29 '17 at 17:15
  • 2
    Прочтите внимательно цитату, что Ant привёл — там всё есть. У Вас, в сущности, два вопроса об одном и том же. Виртуальным деструктор может стать только при наследовании или явном указании, больше никак. Компилятор генерирует деструктор, который должен удалить все объекты, т.е. «пустой» это не верно в общем случае. Но это всё лирика, т.к. код в вопросе даёт неопределённое поведение согласно стандарту. – ixSci Dec 29 '17 at 17:24
  • @ixSci, во, кстати, а давай ты лучше ответом напишешь, что неверно полагать, что сгенерированный деструктор является пустым, а следовательно их вообще нельзя считать одинаковыми? Получишь галочку :) А то вопросы всё-таки довольно сильно разные, хотя и оба о виртуальном деструкторе. – Qwertiy Dec 29 '17 at 17:31
  • Это будет ответ на другой вопрос, всё же. Пусть просто остаётся закрытым, эти вопросы правда одинаковые. – ixSci Dec 29 '17 at 17:34
  • @ixSci, это два совершенно разных частных случая - в этом вопорсе я предполгал, что деструктор nop, соответственно никакой деструктор вообще вызываться не будет, а в том вопросе - что если ничего не изменилось в классе, то и деструкторы будут одинаковыми, поэтому при вызове отработают корректно. Давай я дополню вопрос, чтобы такой ответ больше ему соответствовать, потому что с моей точки зрения, эти вопросы совершенно разные. – Qwertiy Dec 29 '17 at 17:36
  • @ixSci, я дополнил вопрос своими рассуждениями, прошу ответить, что они неверны. – Qwertiy Dec 29 '17 at 17:41
  • 1
    Для этого вопрос должен пройти процедуру переоткрытия. Я считаю, что этого делать не нужно, и ответ есть в другом вопросе. Если пользователи посчитают иначе — вопрос откроют. Но Вы это сами прекрасно знаете. – ixSci Dec 29 '17 at 17:45
  • @ixSci, ты единолично закрыл как обладатель золотого знака. Я бы мог так же переоткрыть как модератор. И ты бы тоже мог. Участия других пользователей я что-то пока не заметил. – Qwertiy Dec 29 '17 at 17:55
  • 1
    Да, я закрыл и считаю это верным. Ответ на вопрос есть в другом вопросе. В Вашем коде неопределённое поведение. Больше говорить тут не о чем. У Вас уже 3 вопроса на одну и ту же тему. Зачем их плодить, когда можно просто прочитать одну цитату Antа, приведённую в самом начале его ответа? – ixSci Dec 29 '17 at 17:59
  • @ixSci, ну пор указатели-то вообще другой - там ничего про деструкторы нет. А этот вообще возник из-за комментария alexolut'а к вопорсу про указатели. Кстати, надо его подправить, вероятно, чтоб там было только обсуждаемое UB. – Qwertiy Dec 29 '17 at 18:02
  • В его текущей форме вопрос не кажется мне дубликатом. // Надеюсь, я не начинаю войну открытий/закрытий. Заранее сорри. – VladD Dec 30 '17 at 17:22
  • Хотя ответ на другой вопрос, кажется, подходит к этому. – VladD Dec 30 '17 at 17:23
  • @VladD, мне здесь хочется услышать ответ про непустой конструктор. – Qwertiy Dec 30 '17 at 20:28
  • 1
    @ixSci, напишешь ответ? – Qwertiy Dec 30 '17 at 20:29
  • @Vlad открыл, он пусть и отвечает. Если бы я считал, что этот вопрос нуждается в ответе, то не закрывал бы его изначально. – ixSci Dec 31 '17 at 06:34

2 Answers2

2

Ответ на этот вопрос по сути совпадает с этим ответом. Виртуальным деструктор может стать только при наследовании или явном указании, больше никак. Компилятор генерирует деструктор, который должен удалить все объекты, т.е. «пустой» это не верно в общем случае. В стандарте нет исключений для этого случая, код в вопросе даёт неопределённое поведение согласно стандарту.

Дополнительно, пустой с точки зрения исходного кода деструктор на деле не является пустым, в него вкладывается логика по деаллокации экземпляра класса. Поэтому деструкторы разных классов по сути являются разными, не взаимозаменяемыми.

VladD
  • 206,799
1

Как известно, при необходимости удаления через указатель на родительский класс, класс должен иметь виртуальный деструктор, чтобы оператор delete вызвал верный деструктор дочернего класса.

Если дело дошло до виртуальных функций и до удаления объекта по указателю на базовый класс, то рекомендуется писать виртуальные деструкторы, хотя бы и пустые. Потом меньше возни будет их добавлять.

Опять же любая программа имеет тенденцию стать библиотекой и в таком качестве следующие пользователи начинают производить свои классы от Ваших классов. Тут и пригодится виртуальный деструктор.

Что касается приведенного примера, то в нем нет ни виртуальных функций, ни НЕОБХОДИМОСТИ удалять объект класса по по указателю на базовый класс. В качестве иллюстрации того, что в С++ МОЖНО обойтись и без виртуальных деструкторов такой пример имеет право на существование. Но в реальном коде с более-менее развитой системой иерархии классов виртуальные деструкторы must have.

pepsicoca1
  • 5,019