Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. C++ Dictionary
  3. Abstract Class (Pure Virtual Functions)

Abstract Class (Pure Virtual Functions)

A class that has at least one pure virtual function (= 0) is called an abstract class and cannot be instantiated directly. Abstract classes are used to define interfaces and common design contracts. A class where all members are pure virtual functions is the C++ equivalent of an interface in Java or C#.

Syntax

// Declares a pure virtual function with = 0.
// A class with at least one pure virtual function becomes an abstract class.
class AbstractBase {
public:
    virtual void pureMethod() = 0;  // pure virtual function (no implementation)

    virtual void normalMethod() {
        // regular virtual function (can have an implementation)
    }

    virtual ~AbstractBase() {}  // virtual destructor is also required
};

// AbstractBase obj;  // compile error (abstract class cannot be instantiated)

// Overriding all pure virtual functions in a derived class creates a concrete class.
class ConcreteClass : public AbstractBase {
public:
    void pureMethod() override {
        // concrete implementation goes here
    }
};

ConcreteClass obj;  // OK (all pure virtual functions are implemented)

// Interface pattern: a class where all members are pure virtual functions
class IAttackable {
public:
    virtual void attack() = 0;
    virtual void defend() = 0;
    virtual ~IAttackable() {}
};

Syntax Reference

Syntax / ConceptDescription
virtual void f() = 0Declares a pure virtual function. It has no implementation and forces derived classes to override it.
Abstract classA class with at least one pure virtual function. It cannot be instantiated and must be used through derived classes.
Concrete classA class that inherits from an abstract class and overrides all pure virtual functions. It can be instantiated.
Interface designA pattern that uses a class whose all members are pure virtual functions as an interface. Combined with multiple inheritance, a single class can implement multiple interfaces.

Sample Code

eva_abstract.cpp
#include <iostream>
#include <string>
#include <vector>

// Interface: IAttackable
// A pure interface representing the ability to attack and defend.
class IAttackable {
public:
    virtual void attack() = 0;
    virtual void defend() = 0;
    virtual ~IAttackable() {}
};

// Abstract class: Angel (common base for Angels)
// Inherits IAttackable and adds the pure virtual function describe().
class Angel : public IAttackable {
protected:
    std::string name;
    int coreHP;

public:
    Angel(const std::string& name, int coreHP)
        : name(name), coreHP(coreHP) {}

    virtual void describe() = 0;

    void showStatus() {
        std::cout << "[" << name << "]  Core HP: " << coreHP << std::endl;
    }

    virtual ~Angel() {}
};

// Concrete class: Sachiel (3rd Angel)
class Sachiel : public Angel {
public:
    Sachiel() : Angel("Sachiel (3rd Angel)", 3000) {}

    void describe() override {
        std::cout << name << ": A giant humanoid Angel with two horns and an exposed skeleton." << std::endl;
    }

    void attack() override {
        std::cout << name << " fires a proton cannon!" << std::endl;
    }

    void defend() override {
        std::cout << name << " deploys an A.T. Field." << std::endl;
    }
};

// Concrete class: Ramiel (5th Angel)
class Ramiel : public Angel {
public:
    Ramiel() : Angel("Ramiel (5th Angel)", 8000) {}

    void describe() override {
        std::cout << name << ": A geometrically perfect octahedron Angel." << std::endl;
    }

    void attack() override {
        std::cout << name << " fires a charged particle beam!" << std::endl;
    }

    void defend() override {
        std::cout << name << " covers all sides with an ultra-hard A.T. Field." << std::endl;
    }
};

// Concrete class: Bardiel (8th Angel)
class Bardiel : public Angel {
public:
    Bardiel() : Angel("Bardiel (8th Angel)", 5500) {}

    void describe() override {
        std::cout << name << ": A parasitic Angel that infects and takes over other units." << std::endl;
    }

    void attack() override {
        std::cout << name << " uses infected tentacles to attack!" << std::endl;
    }

    void defend() override {
        std::cout << name << " uses the host body as a shield." << std::endl;
    }
};

void simulateBattle(Angel* angel) {
    angel->showStatus();
    angel->describe();
    angel->defend();
    angel->attack();
    std::cout << std::endl;
}

int main() {
    std::vector<Angel*> angels;
    angels.push_back(new Sachiel());
    angels.push_back(new Ramiel());
    angels.push_back(new Bardiel());

    std::cout << "=== Angel Interception Simulation ===" << std::endl << std::endl;

    for (int i = 0; i < (int)angels.size(); i++) {
        simulateBattle(angels[i]);
    }

    // Can also be used as an IAttackable pointer
    std::cout << "=== Call via interface pointer ===" << std::endl;
    IAttackable* iface = angels[0];
    iface->attack();
    std::cout << std::endl;

    for (int i = 0; i < (int)angels.size(); i++) {
        delete angels[i];
    }

    return 0;
}
g++ -std=c++11 eva_abstract.cpp -o eva_abstract
./eva_abstract
=== Angel Interception Simulation ===

[Sachiel (3rd Angel)]  Core HP: 3000
Sachiel (3rd Angel): A giant humanoid Angel with two horns and an exposed skeleton.
Sachiel (3rd Angel) deploys an A.T. Field.
Sachiel (3rd Angel) fires a proton cannon!

[Ramiel (5th Angel)]  Core HP: 8000
Ramiel (5th Angel): A geometrically perfect octahedron Angel.
Ramiel (5th Angel) covers all sides with an ultra-hard A.T. Field.
Ramiel (5th Angel) fires a charged particle beam!

[Bardiel (8th Angel)]  Core HP: 5500
Bardiel (8th Angel): A parasitic Angel that infects and takes over other units.
Bardiel (8th Angel) uses the host body as a shield.
Bardiel (8th Angel) uses infected tentacles to attack!

=== Call via interface pointer ===
Sachiel (3rd Angel) fires a proton cannon!

Common Mistake 1: Forgetting to override all pure virtual functions

If a derived class does not override all pure virtual functions from the abstract base class, the derived class also becomes abstract and cannot be instantiated.

// NG: derived class missing the describe() override
class IncompleteAngel : public Angel {
public:
    void attack() override { std::cout << "attack" << std::endl; }
    void defend() override { std::cout << "defend" << std::endl; }
    // describe() is not overridden -> IncompleteAngel is still abstract
};

OK: Override all pure virtual functions from the base class.

// OK: all pure virtual functions are overridden
class CompleteAngel : public Angel {
public:
    CompleteAngel() : Angel("Test Angel", 1000) {}
    void describe() override { std::cout << "complete implementation" << std::endl; }
    void attack()   override { std::cout << "attack" << std::endl; }
    void defend()   override { std::cout << "defend" << std::endl; }
};

Common Mistake 2: Missing virtual destructor

Without a virtual destructor in the abstract base class, the derived class destructor is not called when deleting through a base class pointer, causing resource leaks.

// NG: no virtual destructor
class BadBase {
public:
    virtual void pureMethod() = 0;
    // ~BadBase() is not virtual -> derived destructor is not called on delete
};

OK: Define a virtual destructor.

// OK: define a virtual destructor
class GoodBase {
public:
    virtual void pureMethod() = 0;
    virtual ~GoodBase() {}  // ensures derived destructor is called correctly
};

Overview

A class with at least one pure virtual function (virtual void f() = 0) is an abstract class. Attempting to instantiate it directly results in a compile error. Abstract classes enforce a design contract that derived classes must provide concrete implementations for all pure virtual functions. When all pure virtual functions are overridden, the derived class becomes a concrete class that can be instantiated. The pattern of making all members pure virtual functions is widely used in C++ as an interface pattern, and multiple interfaces can be implemented in a single class using multiple inheritance. When working with abstract class pointers, always define a virtual destructor to ensure the correct destructor is called when deleting through a base class pointer.

If you find any errors or copyright issues, please .