Start learning free

LESSON 185 OF 343 · OBJECT-ORIENTED PROGRAMMING

Interfaces in C++: Pure Virtual Classes

Lesson Read the full explanation

TL ; DR:

An interface is a pure contract — a list of methods that a class promises to implement, with no shared data and no shared code. Unlike inheritance ("is a"), interfaces express "can do".


// C++ uses a class with only pure virtual methods as an interface:
class Speaker {
public:
    virtual void speak() = 0;
    virtual ~Speaker() = default;
};
class Dog : public Speaker {
public:
    void speak() override { cout << "Woof" << endl; }
};


Full lesson:

An interface defines what a class can do, not how it does it or what it is. A Truck, a Robot, and a Drone aren't the same kind of thing — but they can all Move(). You'd put Move() in a Movable interface and have each one implement it.

Interface vs abstract class

Abstract classInterface
Has fieldsYesUsually no
Has method bodiesYes (some)No (or default impls only)
Multiple "inheritance"Usually noYes — a class can implement many interfaces
Models"is a""can do"

A class inherits from at most one parent class but can implement many interfaces. That's why interfaces are the right tool for cross-cutting capabilities like Comparable, Serializable, Iterable, etc.

The language landscape

  • C# / Java — first-class interface keyword. C# uses : for both inheritance and implementation; Java uses extends for inheritance and implements for interfaces.
  • Python — no separate interface; abstract base classes (ABCs) with all-abstract methods serve the same role.
  • JavaScript — no interface keyword in plain JS (TypeScript has it). The convention is a stub class.
  • C++ — a class with only pure-virtual methods is an interface. Multiple inheritance lets a class implement several.

Your task

The Speaker interface (or interface-like base) is already declared. Create a Dog class that implements it, with a speak() method that prints "Woof".

Expected output:

Woof
STEP 1 OF 2
    Ctrl + Enter to check

    C++ · OBJECT-ORIENTED PROGRAMMING

    Interfaces in C++, explained

    What an interface is

    An interface describes what a class can do, without saying how it does it and without storing any data. A Truck, a Robot and a Drone are different kinds of things, but all three can move. If you write the promise "I can move" once, as an interface, any code that needs something movable can work with all three.

    Inheritance models "is a": a Dog is an Animal. An interface models "can do": a Dog can speak. The same class can be both.

    How C++ expresses an interface

    C++ has no interface keyword. By convention, a class that contains only pure virtual functions plays that role. A pure virtual function is a virtual function declared with = 0 instead of a body:

    class Speaker {
    public:
        virtual void speak() = 0;
        virtual ~Speaker() = default;
    };
    

    Three things are worth noticing:

    • The class is abstract. A class with at least one pure virtual function can't be instantiated. Speaker s; does not compile.
    • The members are public. A class is private by default, so the public: label is what lets other code call speak through a Speaker.
    • The destructor is virtual. Code that holds a Speaker* may delete it. Without a virtual destructor, deleting a derived object through a base pointer is undefined behaviour. = default asks the compiler to generate the usual empty body.

    Implementing an interface

    A class implements the interface by inheriting from it publicly and providing a body for every pure virtual function:

    class Dog : public Speaker {
    public:
        void speak() override { cout << "Woof" << endl; }
    };
    

    The override keyword is optional but valuable. It tells the compiler that this function must replace a virtual function of a base class. If you misspell the name or change the parameter list, the code stops compiling instead of silently creating an unrelated function.

    Public inheritance means a Dog can be used wherever a Speaker is expected. That is the point of an interface: code written against Speaker doesn't need to know which concrete class it has.

    vector<Speaker*> speakers = { new Dog, new Cat };
    for (Speaker* s : speakers) {
        s->speak();   // calls Dog::speak, then Cat::speak
    }
    for (Speaker* s : speakers) delete s;
    

    Which speak runs is decided when the program runs, based on the real type of each object. This is runtime polymorphism.

    Interface versus abstract class

    Abstract classInterface
    Data membersAllowedUsually none
    Method bodiesSome are allowedNone, only pure virtual functions
    Combining severalPossible but riskyA class can implement many
    Models"is a""can do"

    In C++ the difference is a matter of discipline, not syntax. Both are classes with pure virtual functions. If you add a data member or a function with a body, you have an abstract base class instead of a pure interface.

    Implementing several interfaces

    C++ supports multiple inheritance, so a class can list several interfaces:

    class Flyer {
    public:
        virtual void fly() = 0;
        virtual ~Flyer() = default;
    };
    
    class Bird : public Speaker, public Flyer {
    public:
        void speak() override { cout << "Tweet" << endl; }
        void fly() override { cout << "Flap" << endl; }
    };
    

    Multiple inheritance is safe here because the interfaces carry no data, so there is no shared state to conflict. A Bird can be passed as a Speaker& or as a Flyer&.

    Common mistakes

    • Leaving one pure virtual function unimplemented. The derived class stays abstract, and Dog rex; fails to compile. If an interface has three functions, the concrete class needs all three.
    • Forgetting public before the base name. In a class, class Dog : Speaker means private inheritance, so outside code can't treat a Dog as a Speaker.
    • Forgetting public: inside the derived class. The speak function would be private, and calling rex.speak() from another class fails.
    • Omitting the virtual destructor. Everything seems to work until a delete through a base pointer skips the derived destructor.
    • Different signatures. void speak() const override doesn't match void speak(). With override the compiler reports it.

    The lesson's exercise

    The Speaker interface is already written. The task is a Dog class whose speak() prints Woof, and the lesson's code then calls it from mainFunction.

    1. Declare the class. Write class Dog : public Speaker, open a public: section, and close the class with };. The semicolon after the closing brace is required for every class.
    2. Implement the function. Add void speak() override with a body that prints Woof using cout.
    class Dog : public Speaker {
    public:
        void speak() override {
            cout << "Woof" << endl;
        }
    };
    

    With this in place, Dog rex; rex.speak(); prints:

    Woof
    

    Key takeaways

    • An interface in C++ is a class made only of pure virtual functions (= 0) and a virtual destructor.
    • A class implements it with public inheritance and a body for every pure virtual function.
    • Mark overriding functions with override so the compiler checks the signature.
    • Interfaces express "can do", and one class can implement many of them.
    • Always give an interface a virtual destructor.
    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free