When dealing with inheritance, it always preferable to provide a virtual destructor. Following example shows the reason why:
#include <iostream>
class Base
{
public:
Base()
{
std::cout << "Base constructor" << '\n';
}
~Base()
{
std::cout << "Base destructor" << '\n';
}
};
class Derived : public Base
{
public:
Derived()
{
std::cout << "Derived constructor" << '\n';
}
~Derived()
{
std::cout << "Derived destructor" << '\n';
}
};
int main(int argc, char const *argv[])
{
Derived *d{new Derived};
Base *base{d};
delete base;
return 0;
}Here, we have created Derived object dynamically and initialize it to the pointer of Derived type. We then initialized pointer of Base type with the pointer of Derived type.
Now, when we delete the object using Base pointer, the base class destructor version would be called. Thus, running the above program gives following result:
Base constructor
Derived constructor
Base destructor
We have an issue here. If derived class is dynamically allocating some memory then the memory would not get released as destructor is not getting invoked.
To solve such issue, we should always make base class destructor virtual so that if class inherit the base class, the destructor should get called if object is accessed using base class reference or pointer.
Corrected program:
#include <iostream>
class Base
{
public:
Base()
{
std::cout << "Base constructor" << '\n';
}
virtual ~Base()
{
std::cout << "Base destructor" << '\n';
}
};
class Derived : public Base
{
public:
Derived()
{
std::cout << "Derived constructor" << '\n';
}
~Derived()
{
std::cout << "Derived destructor" << '\n';
}
};
int main(int argc, char const *argv[])
{
Derived *d{new Derived};
Base *base{d};
delete base;
return 0;
}
We just need to make Base class destructor virtual.