Destructor

Types of destructors:-

Normal (Non-Virtual) Destructor

When you delete a derived object through a base class pointer without a virtual destructor, only the base class destructor is called, not the derived one.

Example:

Copy#include <iostream>
using namespace std;

class Base {
public:
    ~Base() { cout << "Base Destructor\n"; }
};

class Derived : public Base {
public:
    ~Derived() { cout << "Derived Destructor\n"; }
};

int main() {
    Base* obj = new Derived();  // base pointer, derived object
    delete obj;                 // only Base destructor called!
}

Output:

CopyBase Destructor

πŸ”΄ Problem:
The Derived destructor is never called. If Derived allocated resources (like heap memory, file handles, sockets), they would not be released, causing memory leaks.

Virtual Destructor

When you declare the destructor as virtual in the base class, C++ ensures that the destructor of the most derived object is called first (like how virtual functions work with dynamic dispatch).

Fixed Example:

Copy#include <iostream>
using namespace std;

class Base {
public:
    virtual ~Base() { cout << "Base Destructor\n"; }
};

class Derived : public Base {
public:
    ~Derived() { cout << "Derived Destructor\n"; }
};

int main() {
    Base* obj = new Derived();
    delete obj;   // both destructors called
}

Output:

CopyDerived Destructor
Base Destructor

βœ… Now cleanup is correct:

  • First Derived destructor runs (releases derived resources).

  • Then Base destructor runs (releases base resources).


3. Why Virtual Destructors Work (Internals)

  • A V-Table (Virtual Table) is created for classes with virtual methods (including destructors).

  • Each object stores a hidden pointer (vptr) to its class’s V-Table.

  • When you call delete obj;, the runtime checks the vtable entry for destructor of the actual object type.

  • This ensures the correct destructor chain (Derived β†’ Base).


4. When to Use Virtual Destructors

  • If a class is intended to be inherited and will be deleted through a base class pointer β†’ make destructor virtual.

  • If a class is not meant to be inherited β†’ no need for virtual destructor (avoids vtable overhead).


5. Virtual Destructor vs Virtual Functions

  • Similar mechanism: Both use vtables for dynamic dispatch.

  • Destructor difference: Always called in chain order:

    • Derived destructor β†’ Base destructor (safe cleanup).

6. Special Cases

  1. Pure Virtual Destructor

    • You can even make a destructor pure virtual:
    Copyclass Abstract {
    public:
        virtual ~Abstract() = 0; // pure virtual destructor
    };
    Abstract::~Abstract() { cout << "Abstract Destructor\n"; }
    
    • Still requires a definition (because destructors always get called).
Updated on