[с++] виртуальный деструктор
Abstract1* p = new Derive;Само собой, если в Abstact1 деструктор не виртуальный, то именно он и вызовется вместо деструктора потомка.
delete p;
Но вылетает Debug error, код я привел выше.
ошибка с памятью.. какой-то объект залез на другой и его хвост был удален...
Приведен код полностью, больше в программе ничего нет.
Сразу встанет все на свои места
Из new возвращается точно такой же указатель, который передается в delete. Если, конечно, я правильно тебя понял.
Возможно, немного оффтоп, но существует мнение, что множественное наследование - не очень хороший тон программирования и в большинстве случаев можно обойтись без него ("Совершенный код", Мак Коннелл).
Ну если из new вылез бы тот же самый указатель, что и залез в delete, то и ошибки никакой не было... что на самом деле хуже, если бы она была, т.к. по крайней мере, ты узнал, что у тебя косяк.
Я смотрел, что передается в реализацию delete и что возвращается из new. Дебаггером. Абсолютно одинаковые указатели...
Я не спец в плюсах, но казалось бы, если метод не виртуальный, то вставляется вызов, соответствующий статическому типу переменной (в данном случае Abstract1* а не динамическому (Derive*). То есть вызовется деструктор класса Abstract1, который неправильно почистит память, так как на самом деле там объект класса Derive.
Какую еще память он тебе должен почистить? Насколько я понимаю, delete действительно должна вызвать деструктор Abstract1, который ничего не делает, после чего пометить память как свободную, но не давать при этом сбоев.
А как при уничтожении объекта определяется его тип?
Скомпилил gcc — никаких ассертов не печатает.
Собери под релизом. Думать будет легче. Действительно вызывается только деструктор ~Abstract1.
Если через указатель, то тип определяется через тип переменной, передаваемой оператору delete.
Обзовем его Class. Если при этом у какого-либо из предков Class был объявлен виртуальный деструктор, то перед освобождением памяти вызывается деструктор по таблице виртуальных функций, и он будет соответствовать фактическому типу объекта. Если виртуальных деструкторов не было, то вызывается деструтор типа Class.
А вот что происходит со множественным наследованием, я не совсем понимаю. Полистал Страуструпа, но пока не нашел (
Если через указатель, то тип определяется через тип переменной, передаваемой оператору delete.То есть, в данном случае, Abstract1. Объект класса Derive убивается как если бы он был Abstract1.
Ну да, в общем-то. Т.ч. я не вижу никаких причин возникать ошибке памяти.

У тебя 1) ошибка в программе, 2) на нее ругается компилятор (или хз кто).
Что непонятно-то ?
А представь, Derive будет толстым, а удалится пустой Abstract1. Мож runtime перестраховывается

Дебажный delete "видит" неиспользуемые программой блоки (потипу GC) в таких тривиальных случаях и ругается.
1. Ошибки нет.
2. Компилятор не ругается даже ворнингами.
Хз, может быть. По крайней мере, звучит правдоподобно.
The C++ language standard is unusually clear on this topic. When you try to delete a derived class object through a base class pointer and the base class has a nonvirtual destructor (as EnemyTarget does the results are undefined. That means compilers may generate code to do whatever they like: reformat your disk, send suggestive mail to your boss, fax source code to your competitors, whatever.
Оставить комментарий
erotic
При запуске вылетает ошибка
Причем если virtual поставить перед деструктором Abstract1 (неважно, стоит ли при этом virtual перед деструктором Abstract2 или нет то нормально вызывается деструктор Derive.
В чем дело?