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 pure virtual function is a virtual member function declared in a base class that lacks a default implementation within the class definition and mandates that any concrete derived class provide its own implementation. It is declared by appending the pure-specifier (= 0) to the function signature.
class AbstractBase {
public:
    // Pure virtual function declaration
    virtual void execute() = 0; 
    
    // Pure virtual destructor
    virtual ~AbstractBase() = 0; 
};

Mechanics and Compiler Behavior

Abstract Class Generation The presence of one or more pure virtual functions renders the enclosing class an abstract class. The compiler strictly prohibits the instantiation of an abstract class. Objects of this type cannot be created, passed by value, or returned by value; they may only be interacted with via pointers or references. Vtable Resolution and Construction/Destruction At the ABI (Application Binary Interface) level, the compiler allocates a slot in the virtual method table (vtable) for a pure virtual function. Instead of pointing to a valid method address, this slot is typically populated with a pointer to a compiler-provided runtime error handler (e.g., __cxa_pure_virtual in GCC/Clang). According to the C++ Standard, making a virtual call to a pure virtual function during object construction or destruction results in Undefined Behavior. While many compilers implement a runtime handler that traps this and terminates the program, termination is not guaranteed by the language. Conversely, a direct (statically resolved) call to a pure virtual function using the scope resolution operator (e.g., AbstractBase::execute();) during construction or destruction is perfectly valid and well-defined, provided the function has an out-of-line definition. Derived Class Propagation When a derived class inherits from an abstract base class, it must override all pure virtual functions to become a concrete (instantiable) class. If the derived class fails to override even one pure virtual function, it inherits the pure virtual function itself without an override. Consequently, the function remains pure, and the derived class also becomes an abstract class.
class ConcreteDerived : public AbstractBase {
public:
    // Overriding the pure virtual function makes this class instantiable
    void execute() override {
        // Implementation details
    }
    
    ~ConcreteDerived() override = default;
};

Out-of-Line Definitions and Pure Virtual Destructors

While a pure virtual function dictates that derived classes must provide an override, C++ permits the base class to provide a body for the pure virtual function. This definition must be provided out-of-line (outside the class declaration). Providing a body does not change the abstract nature of the base class, nor does it relieve derived classes of the obligation to override the function. It simply provides a common base implementation that derived classes can explicitly invoke via the scope resolution operator (::). A critical rule applies to pure virtual destructors. Declaring a pure virtual destructor (virtual ~Base() = 0;) is a common idiom to make a class abstract without adding other pure virtual functions. However, it is the only pure virtual function that strictly must be given an out-of-line definition. Because derived class destructors implicitly call the base class destructor during the destruction sequence, failing to define a pure virtual destructor will result in a linker error.
class Base {
public:
    virtual void process() = 0; // Pure virtual function
    virtual ~Base() = 0;        // Pure virtual destructor
};

// Out-of-line definition of a pure virtual function
void Base::process() {
    // Base implementation logic
}

// Mandatory out-of-line definition for a pure virtual destructor
Base::~Base() {
    // Base cleanup logic
}

class Derived : public Base {
public:
    void process() override {
        // Derived classes must still override, but can statically call the base implementation
        Base::process(); 
    }
    
    // Implicitly calls Base::~Base() during destruction
    ~Derived() override = default; 
};
Master C++ with Deep Grasping Methodology!Learn More