381

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?

Nick Bolton
  • 34,516
  • 66
  • 162
  • 230

7 Answers7

513

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

Lou Franco
  • 83,503
  • 14
  • 127
  • 183
  • What about pure virtual destructors? My linker is trying to call it at the end of my inherited class's non-virtual destructor; – cjcurrie Feb 05 '13 at 05:42
  • 42
    you can't have a pure virtual destructor without a body. Just give it an empty body. With a regular pure virtual method, the overriding function is called instead, with destructors, they are all called, so you have to provide a body. The =0 just means that it must be overridden, so still a useful construct if you need it. – Lou Franco Feb 05 '13 at 13:49
  • 1
    This question might be related and help [questions/15265106/c-a-missing-vtable-error](http://stackoverflow.com/questions/15265106/c-a-missing-vtable-error). – Paul-Sebastian Manole Dec 20 '14 at 20:16
  • Why doesn’t Nick Bolton’s code cause a segmentation fault although it calls the base destructor twice, while calling `delete` on a pointer to the base class twice does cause a segmentation fault? – Maggyero Jan 10 '18 at 18:07
  • 3
    You are not guaranteed a segmentation fault with any wrong code. Also, calling a destructor does not release memory. – Lou Franco Jan 10 '18 at 23:08
97

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

Community
  • 1
  • 1
Brian R. Bondy
  • 314,085
  • 114
  • 576
  • 619
29

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
};
Wodzu
  • 6,705
  • 8
  • 57
  • 99
  • 1
    what if ~B is not declared virtual? Is ~C still virtual? – Will Feb 23 '11 at 22:07
  • 5
    Yes. When a virtual method (any, not just the destructor) is declared virtual, all overrides of that method in derived classes are automatically virtual. In this case, even if you don't declare ~B virtual, it still is, and so is ~C. – boycy Dec 08 '11 at 16:33
  • 1
    But unlike other overridden methods having the same name and parameters of their corresponding methods in the base class, the destructor name is different.Will it matter? @boycy – Yuan Wen Aug 19 '16 at 02:48
  • 1
    @YuanWen no it won't, the (one and only) derived destructor always overrides its base class's (one and only) destructor. – boycy Aug 30 '16 at 11:08
11

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.

Michel Keijzers
  • 13,956
  • 24
  • 83
  • 111
zar
  • 9,241
  • 10
  • 74
  • 145
  • Good illustration. If you try to call base class destructor from the derived class you should get an compiler error similar to "error: no matching function for call to ‘BASE::BASE()’ ~BASE();" At least this is the behavior from my g++ 7.x compiler. – Kemin Zhou Nov 08 '19 at 17:39
10

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.

itsmatt
  • 30,403
  • 10
  • 97
  • 160
6

No. It's automatically called.

Benoît
  • 16,019
  • 7
  • 43
  • 64
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

Adarsh Kumar
  • 133
  • 9