Abstract Classes
An abstract class is a class that defines an interface — a set of operations any derived class must provide — without necessarily implementing all of them itself. In C++, a class becomes abstract by declaring at least one pure virtual function.
Pure virtual functions
A pure virtual function is declared with = 0 instead of a body. It says: “every concrete (instantiable) derived class must provide an implementation of this — the base class does not.”
Declaring a pure virtual function
class Shape {
public:
virtual double area() const = 0; // pure virtual — no implementation here
virtual ~Shape() = default; // virtual destructor (see previous page)
};A worked example: Shape, Circle, Rectangle
An abstract base class with two concrete derived classes
#include <iostream>
class Shape {
public:
virtual double area() const = 0; // must be implemented by derived classes
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159265 * radius * radius;
}
private:
double radius;
};
class Rectangle : public Shape {
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override {
return width * height;
}
private:
double width, height;
};
int main() {
Circle c(4.0);
Rectangle r(3.0, 5.0);
Shape* shapes[] = { &c, &r };
for (Shape* s : shapes) {
std::cout << "Area: " << s->area() << "\n"; // polymorphic call
}
}Shape* shapes[] holds pointers to two different concrete types, but the loop body doesn't need to know which is which — s->area() dispatches to Circle::area() or Rectangle::area() correctly at runtime, exactly the runtime polymorphism described on the previous two pages. This is the real payoff of an abstract base class: code that works with Shape* automatically works with any shape anyone adds in the future.
What if a derived class doesn't implement it?
If a derived class fails to override every pure virtual function it inherits, it remains abstract itself — it inherits the unimplemented obligation along with everything else, and it too cannot be instantiated until something eventually provides the missing implementation.
A derived class that stays abstract
class Triangle : public Shape {
// area() is not overridden here!
};
int main() {
// Triangle t; // Error: cannot instantiate abstract class 'Triangle'
// // (area() is still pure virtual in Triangle)
}Interfaces vs. partial implementations
An abstract class can mix pure virtual functions (the interface) with ordinary member functions and data (shared implementation) — Shape above provides a concrete virtual destructor alongside its pure virtual area(). A class made up entirely of pure virtual functions with no data acts like a pure interface, similar to what other languages call an “interface” type.
What's next
Abstract classes are often paired with operator overloading so custom types work naturally with
+,==,<<, and other operators — covered next.