Topsic
Topsic

Reputation: 109

Will "delete this" in a base class pointer delete the derived class object when you have a virtual destructor?

I have a class hierarchy that's three levels deep, like this:

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;
    }
}

Ok so what I am wondering is what happens when I call foo() on an object of C. Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?

Upvotes: 3

Views: 2643

Answers (3)

Sebastian Graf
Sebastian Graf

Reputation: 3740

delete will always release the memory for the whole object pointed to. This doesn't apply to called destructors however: It will try to call the destructor of the static type of the object to delete. In a polymorphistic scenario, this is often not what you want. Consider this:

struct Base { };

struct Derived : Base
{
    int* i;

    Derived() : i(new int) { }

    ~Derived() { delete i; }
}

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

bad() causes a memory leak, because Deriveds destructor will never be called. This is because the static type of b is Base*, thus Base::~Base will be called. There is no destructor defined in Base, so the default implementation provided by the compiler executes, which does nothing in this particular example.

This however does not apply to your example: You made the root class' destructor virtual, so all derived classes' destructors will be executed as part of the destructor call.

Upvotes: 2

NPE
NPE

Reputation: 500883

Thanks to the virtual destructor in A the code would work correctly destroy the entire instance of C.

Upvotes: 2

jpalecek
jpalecek

Reputation: 47770

Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?

No. It will "do the right thing" (that is, delete the most derived subobject, run all its destructors etc.) provided A (that is, the static type of the pointee of the pointer you delete) has a virtual destructor (and if class A has a virtual destructor, all its descendants have it, too). This holds for multiple inheritance, too.

Upvotes: 5

Related Questions