class Base // Base Class
{
public:
~Base () {} // Destructor for Base()
};
class Derived : public Base // Derived Class
{
public:
~Derived () {} // Destructor for Derived()
};
Base *obj = new Derived(); // Create Base pointer that points to Derived
// Things go wrong here!
delete obj; When obj is being deleted, the destructor for Base will be invoked. This is dangerous because it leaks memory → Derived’s destructor is not called, hence the contents of the Derived class will remain dangling
Virtual destructors make sure that the right destructors are invoked in an intuitive manner
class Base // Base Class
{
public:
virtual ~Base () {} // Destructor for Base()
};
class Derived : public Base // Derived Class
{
public:
~Derived () {} // Destructor for Derived()
};
Base *obj = new Derived(); // Create Base pointer that points to Derived
// All good!
delete obj; Here, when obj is being deleted, the destructor of Derived will first be called and then Base’s destructor is called, thus ensuring no memory leaks and a safe cleanup.