Будет «удалить это» в указателе базового класса удалить производный объект класса, когда у вас есть виртуальный деструктор?

У меня есть иерархия классов, которая имеет три уровня, например:

class A {
public:
virtual ~A() {}

}

class B : public A {
public:
virtual ~B() {}
void foo(E *e) {
e->remove(this);
}
}

class C : public B {
public:
~C() {}
}

class E {
public:
void remove(A *a) {
delete a;
}
}

Хорошо, так что мне интересно, что происходит, когда я звоню foo() на объекте C, Это собирается удалить весь объект или только B а также A часть объекта, и оставить C часть еще в памяти?

2

Решение

Это собирается удалить весь объект или только части B и A объекта и оставить часть C все еще в памяти?

Нет. Он будет «делать правильные вещи» (то есть удалять наиболее производный подобъект, запускать все его деструкторы и т. Д.) При условии A (то есть статический тип указателя указателя, который вы delete) имеет виртуальный деструктор (и если класс A есть виртуальный деструктор, он есть и у всех его потомков). Это относится и к множественному наследованию.

5

Другие решения

Благодаря виртуальному деструктору в A код будет работать правильно уничтожить весь экземпляр C,

2

delete всегда освобождает память для всего объекта, на который указывает
Однако это не относится к вызываемым деструкторам: он попытается вызвать деструктор статического типа удаляемого объекта.
В полиморфном сценарии это часто не то, что вы хотите. Учти это:

struct Base { };

struct Derived : Base
{
int* i;

Derived() : i(new int) { }

~Derived() { delete i; }
}

void bad()
{
Base* b = new Derived;
delete b;
}

bad() вызывает утечку памяти, потому что DerivedДеструктор никогда не будет вызван. Это потому, что статический тип б Base*таким образом Base::~Base будет называться. Там нет деструктора, определенного в BaseТаким образом, выполняется реализация по умолчанию, предоставляемая компилятором, которая ничего не делает в этом конкретном примере.

Это, однако, не относится к вашему примеру: вы сделали виртуальный деструктор корневого класса, поэтому деструкторы всех производных классов будут выполняться как часть вызова деструктора.

2
По вопросам рекламы [email protected]