Introduction
An Abstract Class is a class that cannot be instantiated directly .
It defines a contract — a set of methods that all derived classes must implement.
In C++, a class becomes abstract when it has at least one pure virtual function (= 0).
Used to enforce a common interface across a family of related classes.
Advantages
Enforces a consistent interface across subclasses.
Enables polymorphism — treat different types uniformly via base pointer.
Separates interface from implementation.
Disadvantages
Cannot instantiate the abstract class directly.
All pure virtual methods must be overridden in concrete subclasses.
Adds a layer of indirection (vtable lookup) — minor runtime cost.
Core Concepts
Pure Virtual Function
Declared with = 0 — no body in the base class.
Forces every concrete subclass to provide an implementation.
class Shape {
public:
virtual double area () = 0 ; // pure virtual
virtual void draw () = 0 ; // pure virtual
virtual ~Shape () {} // always virtual destructor
};
// Shape s; // ERROR — cannot instantiate abstract class
Concrete Subclass
A class that inherits from an abstract class and implements all pure virtual methods.
class Circle : public Shape {
double radius;
public:
Circle ( double r ) : radius (r) {}
double area () override {
return 3.14159 * radius * radius;
}
void draw () override {
std ::cout << "Drawing Circle \n " ;
}
};
Abstract Class with Partial Implementation
Abstract classes can also have non-pure virtual methods (with a default body).
Subclasses may override them or use the default.
class Animal {
public:
virtual void sound () = 0 ; // must override
virtual void breathe () { // optional override
std ::cout << "Breathing... \n " ;
}
virtual ~Animal () {}
};
class Dog : public Animal {
public:
void sound () override {
std ::cout << "Woof! \n " ;
}
// breathe() inherited from Animal — no need to override
};
C++ Examples
Basic Abstract Class
#include <iostream>
class Shape {
public:
virtual double area () = 0 ;
virtual double perimeter () = 0 ;
virtual ~Shape () {}
};
class Rectangle : public Shape {
double w, h;
public:
Rectangle ( double w , double h ) : w (w), h (h) {}
double area () override { return w * h; }
double perimeter () override { return 2 * (w + h); }
};
class Circle : public Shape {
double r;
public:
Circle ( double r ) : r (r) {}
double area () override { return 3.14159 * r * r; }
double perimeter () override { return 2 * 3.14159 * r; }
};
int main () {
Shape * s1 = new Rectangle ( 4 , 5 );
Shape * s2 = new Circle ( 3 );
std ::cout << s1-> area (); // 20
std ::cout << s2-> area (); // 28.274...
delete s1;
delete s2;
}
Polymorphism via Abstract Base
#include <vector>
#include <memory>
std ::vector < std ::unique_ptr < Shape >> shapes;
shapes. push_back ( std :: make_unique < Rectangle >( 3 , 4 ));
shapes. push_back ( std :: make_unique < Circle >( 5 ));
shapes. push_back ( std :: make_unique < Rectangle >( 2 , 7 ));
for ( const auto& s : shapes) {
std ::cout << "Area: " << s-> area () << " \n " ;
}
// Area: 12
// Area: 78.539...
// Area: 14
Abstract Class as Interface (all pure virtual)
// Pure interface — no data, no implementation
class ISerializable {
public:
virtual std :: string serialize () = 0 ;
virtual void deserialize ( const std :: string & data ) = 0 ;
virtual ~ISerializable () {}
};
class Config : public ISerializable {
std ::string content;
public:
std :: string serialize () override { return content; }
void deserialize ( const std :: string & data ) override { content = data; }
};
Abstract Class vs Interface (C++)
C++ has no interface keyword — interfaces are simulated with all-pure-virtual abstract classes .
Feature Abstract Class Interface (simulated)
Pure virtual methods Some or all All
Non-virtual methods Allowed Not typical
Data members Allowed Not typical
Multiple inheritance Possible (careful) Common pattern
Rules & Best Practices
Always declare a virtual destructor in abstract base classes.
Use override keyword in derived classes — catches typos at compile time.
Prefer smart pointers (unique_ptr, shared_ptr) when storing polymorphic objects.
Keep abstract classes focused — don’t mix unrelated responsibilities.
// Good practice
class Base {
public:
virtual void doWork () = 0 ;
virtual ~Base () = default ; // virtual destructor
};
class Derived : public Base {
public:
void doWork () override { /* ... */ }
};
Key Takeaways
Abstract class = class with at least one = 0 pure virtual function.
Cannot be instantiated — only used as a base type.
Enables runtime polymorphism via base class pointers/references.
Always add a virtual destructor to avoid undefined behavior on delete.