Do I need to explicitly call the base virtual destructor?

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?


Solution 1:

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

Solution 2:

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().

Solution 3:

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

Solution 4:

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