Skip to content
  • Abstract Classes & Interfaces · C++

Abstract Classes & Interfaces

LearnViaNotes @learnvianotes· 3 min read

A pure virtual function (= 0) has no implementation in the base class. A class with at least one is abstract: it can't be instantiated, only derived from — that's how C++ spells “interface”.

Interface + implementations

C++
#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Notifier {                                   // interface: only pure virtuals
public:
    virtual ~Notifier() = default;
    virtual void send(const std::string& msg) = 0;
    virtual std::string channel() const = 0;
};

class EmailNotifier : public Notifier {
public:
    void send(const std::string& msg) override { std::cout << "email: " << msg << '\n'; }
    std::string channel() const override { return "email"; }
};

class SmsNotifier : public Notifier {
public:
    void send(const std::string& msg) override { std::cout << "sms: " << msg.substr(0, 10) << '\n'; }
    std::string channel() const override { return "sms"; }
};

void alertAll(const std::vector<std::unique_ptr<Notifier>>& targets, const std::string& msg) {
    for (const auto& t : targets) t->send(msg);   // depends only on the interface
}

int main() {
    std::vector<std::unique_ptr<Notifier>> targets;
    targets.push_back(std::make_unique<EmailNotifier>());
    targets.push_back(std::make_unique<SmsNotifier>());
    alertAll(targets, "Server CPU at 97%");
    // Notifier n;   // error: abstract class
}
Output
email: Server CPU at 97%
sms: Server CPU
C++
struct Shape { virtual double area() const = 0; virtual ~Shape() = default; };
struct Square : Shape { double s = 1; };      // forgot to override area → still abstract
int main() {
    Square sq;                                // error: variable type 'Square' is an abstract class
}

Template method pattern

C++
#include <iostream>

class Report {
public:
    void generate() const {              // fixed algorithm (non-virtual)…
        std::cout << "== " << title() << " ==\n";
        body();
        std::cout << "-- end --\n";
    }
    virtual ~Report() = default;
private:
    virtual const char* title() const = 0;    // …customisation points (private virtual is fine)
    virtual void body() const = 0;
};

class SalesReport : public Report {
    const char* title() const override { return "Sales"; }
    void body() const override { std::cout << "total: 42\n"; }
};

int main() { SalesReport{}.generate(); }
Output
== Sales ==
total: 42
-- end --

Pure virtual with a body

C++
#include <iostream>
struct Base {
    virtual ~Base() = 0;                         // pure virtual destructor: makes Base abstract…
    virtual void log() const = 0;
};
Base::~Base() { std::cout << "~Base\n"; }       // …but it MUST still have a body
void Base::log() const { std::cout << "default logging\n"; }   // optional default implementation

struct Impl : Base { void log() const override { Base::log(); } };
int main() { Impl i; i.log(); }
Output
default logging
~Base
Abstract classInterface (C++ convention)
Pure virtual functionsAt least oneAll (plus virtual dtor)
Data membersAllowedNone
Implemented functionsAllowedNone
Multiple inheritancePossible but carefulSafe and common

Can an abstract class have a constructor?

Abstract class vs interface in C++?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report