Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A virtual destructor is a destructor in a base class declared with the virtual keyword. It enables dynamic dispatch for object destruction, ensuring that the most derived class’s destructor is invoked when an object is deleted through a pointer to its base class.

Syntax

class Base {
public:
    virtual ~Base(); // Virtual destructor declaration
};

Mechanics and Execution Flow

When a class declares a virtual destructor, the compiler integrates it into the Virtual Method Table (vtable). Upon invoking the delete operator on a base class pointer, the runtime environment resolves the destructor call dynamically through the vtable rather than statically based on the pointer’s type. This guarantees the standard C++ destruction sequence:
  1. The most derived destructor executes.
  2. Class members are destroyed in reverse order of their initialization.
  3. The base class destructor executes.

Static vs. Dynamic Binding

Without the virtual keyword, the destructor call is statically bound at compile time. Deleting a derived object via a base pointer with a non-virtual destructor results in Undefined Behavior (UB) according to the C++ Standard. Typically, this manifests as only the base class destructor executing, bypassing the derived destructor entirely.
// Static Binding (Non-Virtual)
class BaseStatic {
public:
    ~BaseStatic() {} 
};
class DerivedStatic : public BaseStatic {
public:
    ~DerivedStatic() {}
};

// Dynamic Binding (Virtual)
class BaseDynamic {
public:
    virtual ~BaseDynamic() {} 
};
class DerivedDynamic : public BaseDynamic {
public:
    ~DerivedDynamic() override {}
};

int main() {
    BaseStatic* ptr1 = new DerivedStatic();
    delete ptr1; // UNDEFINED BEHAVIOR: Only ~BaseStatic() is invoked.

    BaseDynamic* ptr2 = new DerivedDynamic();
    delete ptr2; // WELL-DEFINED: ~DerivedDynamic() executes, followed by ~BaseDynamic().
    
    return 0;
}

Pure Virtual Destructors

A destructor can be declared as pure virtual (= 0) to force the base class to become an abstract class, preventing direct instantiation. However, unlike standard pure virtual methods, a pure virtual destructor must have an out-of-line definition. Because the destruction sequence inherently propagates up the inheritance chain, the derived class’s destructor will implicitly invoke the base class’s destructor. If the pure virtual destructor lacks a definition, the linker will throw an unresolved external symbol error.
class AbstractBase {
public:
    virtual ~AbstractBase() = 0; // Pure virtual declaration
};

// Mandatory definition
AbstractBase::~AbstractBase() {
    // Base destruction logic, if any
}

Architectural Rule

In C++ class design, the presence of a virtual destructor is tied to polymorphism. The standard technical guideline (C++ Core Guideline C.35) dictates: A base class destructor should be either public and virtual, or protected and non-virtual.
  • Public and Virtual: Allows the object to be safely destroyed polymorphically via a base class pointer.
  • Protected and Non-Virtual: Prevents polymorphic deletion entirely. If code attempts to delete a derived object through a base pointer, the compiler will reject it, safely avoiding Undefined Behavior at compile time without incurring the overhead of a virtual destructor.
Conversely, if a class is not intended to be used as a base class at all, the destructor should remain public and non-virtual to avoid the memory overhead of a vptr (virtual pointer).
Master C++ with Deep Grasping Methodology!Learn More