Abstract Classes
Overview
Sometimes a Parent Class is so generic that it makes absolutely no sense to ever create an Object out of it. You should be able to create a Circle or a Square, but instantiating a generic Shape object is illogical.
C++ allows you to lock a class so it can NEVER be instantiated. This is called an Abstract Class (or an Interface). You create one by assigning a virtual function the mathematical value of = 0. This is known as a 'Pure Virtual Function'. Any class containing a Pure Virtual Function becomes an Abstract Class. Furthermore, any Child that inherits from it is forcefully required by the compiler to write their own version of that function.
Syntax
#include <iostream>
// 1. ABSTRACT CLASS (Cannot be instantiated!)
class Shape {
public:
// 2. PURE VIRTUAL FUNCTION ('= 0')
// This forces all children to provide their own implementation!
virtual void draw() = 0;
};
// 3. CONCRETE CLASS
class Circle : public Shape {
public:
// 4. Fulfilling the contract!
void draw() override {
std::cout << "Drawing a perfect Circle.\n";
}
};
int main() {
// Shape s; // FATAL ERROR: Cannot instantiate an Abstract Class!
Shape* myShape = new Circle(); // Valid! Polymorphism still works!
myShape->draw();
return 0;
}Common Pitfalls
- The Unimplemented Child. If
Circleinherits fromShapebut forgets to write thedraw()function, the compiler punishes it by makingCirclean Abstract Class as well! You will be completely locked out of creatingCircleobjects until you fulfill the= 0contract.
Interview Questions
interface keyword like Java or C#?No. C++ does not have a formal interface keyword. However, the exact architectural behavior of an interface is achieved by creating a Class where every single method is a Pure Virtual Function (= 0) and it contains absolutely zero member variables.
Real-World Example
Using Abstract Classes to define strict 'Contracts' that plugins or API integrations must follow.
#include <iostream>
// The Contract Interface
class ILogger {
public:
virtual void logError(std::string msg) = 0;
virtual ~ILogger() {} // Always provide a virtual destructor!
};
// The Implementation
class ConsoleLogger : public ILogger {
public:
void logError(std::string msg) override {
std::cout << "[ERROR] " << msg << "\n";
}
};Check Your Knowledge
Test your understanding of Abstract Classes with these quick questions.