Interfaces in C++: A Guide for Those Tired of Googling
\n\nIf you've ever written in Java or C# and then switched to C++, you've probably wondered: "Where's the interface keyword?". Spoiler: it doesn't exist. In C++, interfaces are implemented differently — through abstract classes. And this isn't a bug, it's a feature that provides incredible flexibility.
\n\nOn Stack Overflow, the question "How do you declare an interface in C++?" gathers thousands of views. This means even experienced developers sometimes get confused. Today, we'll finally figure out how to declare an interface in C++ so your code is clean and your compiler is happy.
\n\nWhat is an Interface in C++? (Spoiler: It's an Abstract Class)
\n\nIn classical OOP, an interface is a contract. A class that implements an interface must provide an implementation for all its methods. In C++, this role is played by an abstract class — a class that contains at least one pure virtual function.
\n\nRemember the main rule:
\n- \n
- Interface = a class where all methods are pure virtual. \n
- Abstract class = a class where at least one method is pure virtual (but it can also have regular methods with implementations). \n
For a pure interface, we use the first option: no logic, only declarations.
\n\nHow to Declare a Pure Interface: Basic Syntax
\n\nHere's a minimal example of an interface for a geometric shape:
\n\nclass IShape {\npublic:\n virtual double area() const = 0; // Pure virtual function\n virtual double perimeter() const = 0; // Another one\n virtual ~IShape() {} // Virtual destructor — mandatory!\n};\n\nNotice the = 0 at the end of the declaration. This is the magic marker for "pure virtual". Such a method has no body (implementation) in the base class.
Key points:
\n- \n
- Prefix I in the class name is an unwritten convention for interfaces (I = Interface). You don't have to use it, but it simplifies code reading. \n
- Virtual destructor is mandatory. If you delete an object through a pointer to the interface, without a virtual destructor the behavior is undefined (read: the program will crash). \n
- All methods are public — the interface must be accessible for external calls. \n
Implementing the Interface: From Words to Action
\n\nNow let's write a class that implements our IShape interface. Let it be a circle:
class Circle : public IShape {\nprivate:\n double radius;\npublic:\n explicit Circle(double r) : radius(r) {}\n\n double area() const override {\n return 3.14159 * radius * radius;\n }\n\n double perimeter() const override {\n return 2 * 3.14159 * radius;\n }\n};\n\nThe override keyword (C++11 and newer) is not mandatory, but highly recommended. It forces the compiler to check that you are actually overriding a virtual method from the base class. Misspelled the name? The compiler will say: "Error! No such method in the interface."
Polymorphism in Action
\n\nNow for the interesting part — we can work with different shapes through a single interface:
\n\nvoid printShapeInfo(const IShape& shape) {\n std::cout << "Area: " << shape.area() << "\\n";\n std::cout << "Perimeter: " << shape.perimeter() << "\\n";\n}\n\nint main() {\n Circle c(5.0);\n printShapeInfo(c); // Works!\n return 0;\n}\n\nThe printShapeInfo function takes a reference to IShape. It doesn't care which specific object is passed — a circle, square, or triangle. As long as they implement the interface, everything works. This is polymorphism