softwarelover
softwarelover

Reputation: 1019

How to get virtual destructors to be called in C++?

I am trying to see the effects of calling virtual destructors of classes belonging to a long chain of hierarchy: class A to class E.

Strangely, the destructors do not write anything to the console. I first thought perhaps it was happening because main was exiting too. So, I put all the testing code within a function called test() and invoked from within main() so when test would return, I would see destructor footprints. But, nothing! No "cout" signs on the console show up!

#include <iostream>

using namespace std;

//A constructor cannot be virtual but a destructor can.
class A {
public:
A() {
    cout << "A constructor" << endl;
}
virtual ~A() {cout << "A destructor" << endl;}
};

class B :public A {
public:
    B() {
    cout << "B constructor" << endl;
    }
    virtual ~B() {cout << "B destructor" << endl;}
};

class C :public B {
public:
    C() {
    cout << "C constructor" << endl;
    }
    virtual ~C() {cout << "C destructor" << endl;}
};

class D :public C {
public:
    D() {
    cout << "D constructor" << endl;
    }
    ~D() {cout << "D destructor" << endl;}
};

class E :public D {
public:
    E() {
     cout << "E constructor" << endl;
      }
     ~E() {cout << "E destructor" << endl;}
};

void test() {
   cout << "Test1 begins..." << endl;
   A* a1 = new D();
   cout << "Test2 begins..." << endl;
   A* a2 = new E();
}

int main() {
 test();
 return 0;
}

Upvotes: 1

Views: 71

Answers (2)

David Haim
David Haim

Reputation: 26536

Ummm... you actually leak those.

Every objected created by the new keyword must have an equivilant delete:

void test() {
   cout << "Test1 begins..." << endl;
   A* a1 = new D();
   cout << "Test2 begins..." << endl;
   A* a2 = new E();
   delete a1;
   delete a2;
}

Developers (just in your case) always forgot to delete dynamically allocated objects, so smart pointers were introduce:

void test() {
   cout << "Test1 begins..." << endl;
   std::unique_ptr<A> a1(new D());
   cout << "Test2 begins..." << endl;
   std::unique_ptr<A> a2(new E());
}

no need to worry about a leak, as unique_ptr automatically delete their pointee when they get out of scope.

Upvotes: 6

You never delete your raw pointers. Prefer smart pointers to raw ones.

You should add

delete a1;
delete a2;

near the end of your test.

Try also to create some instances of E as an automatic variable (usually on the call stack). For example, insert

E ee;

in between those two delete-s.

Upvotes: 3

Related Questions