When to use virtual destructors in C++?

Destructors are used to release any resources allocated by the object. In this blog post, I will explain when to use virtual destructors in C++. But before explaining it I want to tell you some contexts where the destructor is invoked implicitly.

Let’s see a few of them,

  • For a constructed object with static storage duration at program termination.
  • For a constructed object with thread storage duration at thread exit.
  • For a constructed object with automatic storage duration when the block in which an object is created exits.
  • For a constructed temporary object when its lifetime ends.
  • A destructor may also be invoked implicitly by using a delete expression for a constructed object allocated by a new expression.

Now let’s come up on the topic that when to use virtual destructors in C++.

As you know by default early binding happens in C++, so when the object pointer of the base class is deleted, that was pointing to the object of its derived class, only the destructor of the base class is invoked; it does not invoke the destructor of the derived class, that leads to bugs.

Consider the below example,

#include<iostream>
using namespace std;


class base
{
public:
    base()
    {
        cout<<"Constructor of base \n";
    }
    ~base()
    {
        cout<<"Destructor of base \n";
    }
};


class derived: public base
{
public:
    derived()
    {
        cout<<"Constructor of  derived \n";
    }
    ~derived()
    {
        cout<<"Destructor of derived \n";
    }
};
int main(void)
{
    derived *d = new derived();
    base *b = d;
    delete b;
    return 0;
}

Output:

Constructor of base
Constructor of  derived
Destructor of base

 

You can see in the above code that, the destructor of base class is invoking beside the derived class object.

You can solve this problem by using the virtual keyword with the destructor. So virtual destructors are useful when you might potentially delete an instance of a derived class through a pointer to the base class. Let’s see an example code,

#include<iostream>
using namespace std;


class base
{
public:
    base()
    {
        cout<<"Constructor of base \n";
    }
    //Destructor with virtual keyword
    virtual ~base()
    {
        cout<<"Destructor of base \n";
    }
};


class derived: public base
{
public:
    derived()
    {
        cout<<"Constructor of  derived \n";
    }
    ~derived()
    {
        cout<<"Destructor of derived \n";
    }
};
int main(void)
{
    derived *d = new derived();
    base *b = d;
    delete b;
    return 0;
}

Output:

Constructor of base
Constructor of  derived
Destructor of derived
Destructor of base

 

Recommended Articles for you: