Question
How to Declare an Interface in C++: Abstract Base Classes Explained
Question
How do you set up a class in C++ that represents an interface? Is an interface in C++ simply an abstract base class?
Short Answer
By the end of this page, you will understand how C++ represents interfaces using abstract base classes, what pure virtual functions do, why virtual destructors matter, and how concrete classes implement those interfaces in real code.
Concept
In C++, there is no separate interface keyword like in some other languages such as Java or C#. Instead, the usual way to model an interface is to create an abstract base class.
A class becomes abstract when it contains at least one pure virtual function. A pure virtual function is declared by assigning = 0 at the end of the function declaration.
class Shape {
public:
virtual double area() const = 0;
};
This means:
Shapecannot be instantiated directly.- Any derived class must provide an implementation for
area()unless it is also abstract. - The class acts as a contract: derived classes promise to provide certain behavior.
In practice, an interface-style class in C++ usually has:
- only pure virtual functions
- no data members
- a
virtualdestructor
For example:
class ILogger {
public:
virtual ~ILogger() = default;
virtual void log(const std::string& message) = 0;
};
This pattern matters because it lets you write code against a common contract instead of a specific implementation. That makes code easier to extend, test, and reuse.
For example, code can depend on ILogger without caring whether the real object writes to a file, the console, or a remote service.
Although an interface in C++ is usually an abstract base class, not every abstract base class is used purely as an interface. Some abstract base classes also contain shared implementation or member data. So the key idea is:
- Interface-style class: abstract base class used mainly as a contract
- General abstract base class: abstract class that may also provide reusable implementation
Mental Model
Think of an interface in C++ like a job description.
The interface says:
- what tasks must be done
- what function names and signatures must exist
- but not exactly how the work is performed
For example, a Printer interface might say every printer must support print().
A laser printer and a PDF printer both satisfy the same job description, but they do the work differently.
So:
- the interface is the contract
- the derived class is the worker fulfilling that contract
- the pure virtual functions are the required tasks
This is why abstract base classes are used for interfaces in C++: they define required behavior without forcing one specific implementation.
Syntax and Examples
Basic interface-style class in C++
class IAnimal {
public:
virtual ~IAnimal() = default;
virtual void speak() const = 0;
};
What this means
IAnimalis abstract becausespeak()is pure virtual.virtual ~IAnimal() = default;makes destruction safe through a base-class pointer.- You cannot create an
IAnimaldirectly.
Implementing the interface
#include <iostream>
using namespace std;
class IAnimal {
public:
virtual ~IAnimal() = default;
virtual void speak() = ;
};
: IAnimal {
:
{
cout << ;
}
};
{
Dog d;
d.();
}
Step by Step Execution
Consider this example:
#include <iostream>
using namespace std;
class IAnimal {
public:
virtual ~IAnimal() = default;
virtual void speak() const = 0;
};
class Dog : public IAnimal {
public:
void speak() const override {
cout << "Woof\n";
}
};
int main() {
IAnimal* animal = new Dog();
animal->speak();
delete animal;
}
Step-by-step
-
IAnimalis declared with a pure virtual functionspeak().
Real World Use Cases
Interfaces in C++ are commonly used when multiple classes should provide the same behavior in different ways.
Common examples
-
Logging systems
ILoggercan be implemented byConsoleLogger,FileLogger, orNetworkLogger.
-
Payment providers
IPaymentProcessorcan be implemented by Stripe, PayPal, or a mock test processor.
-
Game engines
IRenderermight have OpenGL, Vulkan, or DirectX implementations.
-
Device drivers
- A common interface can describe devices that read data, while each device class handles hardware-specific details.
-
Testing and mocking
- If your code depends on an interface, you can replace the real class with a fake or mock version in tests.
Example scenario
class IDataStore {
public:
virtual ~() = ;
= ;
};
Real Codebase Usage
In real projects, interface-style classes are often used to separate what a system does from how it does it.
Common patterns
Dependency injection
A class receives an interface instead of creating a concrete dependency directly.
class ILogger {
public:
virtual ~ILogger() = default;
virtual void log(const std::string& message) = 0;
};
class Service {
private:
ILogger& logger;
public:
Service(ILogger& logger) : logger(logger) {}
void run() {
logger.log("Service started");
}
};
This makes Service easier to test and reuse.
Testing with fake implementations
class FakeLogger : public ILogger {
public:
{
}
};
Common Mistakes
1. Forgetting the virtual destructor
This is one of the most important mistakes.
Broken code
class IAnimal {
public:
virtual void speak() const = 0;
};
If you delete a derived object through an IAnimal*, behavior is unsafe because the base destructor is not virtual.
Correct code
class IAnimal {
public:
virtual ~IAnimal() = default;
virtual void speak() const = 0;
};
2. Trying to instantiate the interface
Broken code
IAnimal animal;
This fails because IAnimal is abstract.
Fix
Instantiate a concrete derived class instead.
Comparisons
| Concept | What it means | Typical contents | Can contain implementation? | Main use |
|---|---|---|---|---|
| Interface-style class in C++ | An abstract base class used as a contract | Pure virtual functions, virtual destructor | Usually no | Define required behavior |
| Abstract base class | A class that cannot be instantiated | One or more pure virtual functions, sometimes data and concrete methods | Yes | Shared design and reusable base behavior |
| Concrete class | A fully implemented class | Normal methods and data members | Yes | Create actual objects |
Interface-style class vs abstract base class
- Every interface-style class in C++ is typically an abstract base class.
- But not every abstract base class is a pure interface.
- Some abstract base classes include common logic for derived classes.
Pure virtual vs regular virtual
Cheat Sheet
Quick reference
Declare an interface-style class
class IExample {
public:
virtual ~IExample() = default;
virtual void doWork() = 0;
};
Implement it
class Example : public IExample {
public:
void doWork() override {
// implementation
}
};
Rules to remember
- C++ has no built-in
interfacekeyword. - Use an abstract base class to model an interface.
- A class becomes abstract when it has at least one pure virtual function.
- Pure virtual syntax:
virtual ReturnType name(...) = 0; - Add a
virtualdestructor for safe polymorphic deletion. - Use
overridein derived classes. - You cannot instantiate an abstract class directly.
FAQ
Is there an interface keyword in C++?
No. C++ usually models interfaces with abstract base classes containing pure virtual functions.
Is an interface in C++ just an abstract base class?
Usually yes. More specifically, an interface-style class is an abstract base class used mainly to define a contract.
What makes a class abstract in C++?
A class is abstract if it has at least one pure virtual function, written with = 0.
Why should an interface have a virtual destructor?
So deleting an object through a base-class pointer works correctly and safely.
Can an abstract base class contain normal method implementations?
Yes. An abstract base class can contain both pure virtual and fully implemented methods. If it does, it is not a pure interface-only design.
Can an interface in C++ have member variables?
It can, but interface-style classes usually avoid data members and focus only on behavior.
Should I use override when implementing interface methods?
Yes. It helps the compiler detect signature mismatches and makes code clearer.
Mini Project
Description
Create a small notification system where different classes send messages in different ways, but all follow the same interface. This demonstrates how C++ interfaces let you write one piece of code that works with many implementations.
Goal
Build an interface-style class for notifications and implement at least two concrete notification types that can be used through the same base interface.
Requirements
- Create an abstract base class named
INotifier - Add a pure virtual function that sends a message
- Add a virtual destructor to the interface
- Implement at least two classes such as
EmailNotifierandSmsNotifier - Write a function that accepts the interface and sends a message through it
Keep learning
Related questions
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Base Class Constructor Rules Explained
Learn how C++ base class constructors are called from derived classes, including order, syntax, defaults, and common mistakes.
C++ Casts Explained: C-Style Cast vs static_cast vs dynamic_cast
Learn the difference between C-style casts, static_cast, and dynamic_cast in C++ with clear examples, safety rules, and real usage tips.