3

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?

6
  • 3
    You have syntax errors. Please fix them. Also, avoid delete this like the plague. Also, void remove(A* a) in class E, but void remove(E* e) in class B? Are you sure? Yikes! Commented Jan 6, 2013 at 14:28
  • You are destroying all the object, and releasing its memory. Commented Jan 6, 2013 at 14:28
  • There are 2 removes in your code. Which one? Commented Jan 6, 2013 at 14:30
  • 2
    Virtuality of destructors is hereditary. Commented Jan 6, 2013 at 14:30
  • Try access a method of an instance of class B after you removed A is an alternative way of checking this. Commented Jan 6, 2013 at 14:31

3 Answers 3

5

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

1 Comment

Is this true for all compilers? I swear I have seen C destroyed without A having declared a virtual destructor. Mainly in gcc.
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.