386
votes

When overriding a class in C++ (with a virtual destructor) I am implementing the destructor again as virtual on the inheriting class, but do I need to call the base destructor?

If so I imagine it's something like this...

MyChildClass::~MyChildClass() // virtual in header
{
    // Call to base destructor...
    this->MyBaseClass::~MyBaseClass();

    // Some destructing specific to MyChildClass
}

Am I right?

7

7 Answers

520
votes

No, destructors are called automatically in the reverse order of construction. (Base classes last). Do not call base class destructors.

97
votes

No you don't need to call the base destructor, a base destructor is always called for you by the derived destructor. Please see my related answer here for order of destruction.

To understand why you want a virtual destructor in the base class, please see the code below:

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


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

When you do:

B *pD = new D();
delete pD;

Then if you did not have a virtual destructor in B, only ~B() would be called. But since you have a virtual destructor, first ~D() will be called, then ~B().

29
votes

What the others said, but also note that you do not have to declare the destructor virtual in the derived class. Once you declare a destructor virtual, as you do in the base class, all derived destructors will be virtual whether you declare them so or not. In other words:

struct A {
   virtual ~A() {}
};

struct B : public A {
   virtual ~B() {}   // this is virtual
};

struct C : public A {
   ~C() {}          // this is virtual too
};
11
votes

No, you never call the base class destructor, it is always called automatically like others have pointed out but here is proof of concept with results:

class base {
public:
    base()  { cout << __FUNCTION__ << endl; }
    ~base() { cout << __FUNCTION__ << endl; }
};

class derived : public base {
public:
    derived() { cout << __FUNCTION__ << endl; }
    ~derived() { cout << __FUNCTION__ << endl; } // adding call to base::~base() here results in double call to base destructor
};


int main()
{
    cout << "case 1, declared as local variable on stack" << endl << endl;
    {
        derived d1;
    }

    cout << endl << endl;

    cout << "case 2, created using new, assigned to derive class" << endl << endl;
    derived * d2 = new derived;
    delete d2;

    cout << endl << endl;

    cout << "case 3, created with new, assigned to base class" << endl << endl;
    base * d3 = new derived;
    delete d3;

    cout << endl;

    return 0;
}

The output is:

case 1, declared as local variable on stack

base::base
derived::derived
derived::~derived
base::~base


case 2, created using new, assigned to derive class

base::base
derived::derived
derived::~derived
base::~base


case 3, created with new, assigned to base class

base::base
derived::derived
base::~base

Press any key to continue . . .

If you set the base class destructor as virtual which one should, then case 3 results would be same as case 1 & 2.

10
votes

No. Unlike other virtual methods, where you would explicitly call the Base method from the Derived to 'chain' the call, the compiler generates code to call the destructors in the reverse order in which their constructors were called.

7
votes

Destructors in C++ automatically gets called in the order of their constructions (Derived then Base) only when the Base class destructor is declared virtual.

If not, then only the base class destructor is invoked at the time of object deletion.

Example: Without virtual Destructor

#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}

Output

Base Constructor
Derived Constructor
Base Destructor

Example: With Base virtual Destructor

#include <iostream>

using namespace std;

class Base{
public:
  Base(){
    cout << "Base Constructor \n";
  }

  //virtual destructor
  virtual ~Base(){
    cout << "Base Destructor \n";
  }

};

class Derived: public Base{
public:
  int *n;
  Derived(){
    cout << "Derived Constructor \n";
    n = new int(10);
  }

  void display(){
    cout<< "Value: "<< *n << endl;
  }

  ~Derived(){
    cout << "Derived Destructor \n";
    delete(n);  //deleting the memory used by pointer
  }
};

int main() {

 Base *obj = new Derived();  //Derived object with base pointer
 delete(obj);   //Deleting object
 return 0;

}

Output

Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

It is recommended to declare base class destructor as virtual otherwise, it causes undefined behavior.

Reference: Virtual Destructor

6
votes

No. It's automatically called.