An interface is typically represented using an Abstract Base Class (ABC). An abstract base class is a class that contains at least one pure virtual function. Abstract classes cannot be instantiated directly and are intended to be subclassed by other classes that implement the pure virtual functions. This concept allows C++ to provide a similar behavior to interfaces found in other programming languages like Java or C#.
= 0
syntax.A pure virtual function is declared in the base class but has no implementation. Derived classes must provide an implementation for these functions in order to be instantiated.
Syntax for declaring a pure virtual function:
virtual return_type function_name(parameters) = 0;
The = 0
syntax marks the function as pure virtual, making the containing class abstract.
class Shape {
public:
// Pure virtual function making this class abstract
virtual void draw() const = 0;
virtual double area() const = 0;
virtual ~Shape() {} // Virtual destructor for proper cleanup
};
In this example, the Shape
class has two pure virtual functions: draw()
and area()
. These functions must be implemented by any class that inherits from Shape
, and Shape
cannot be instantiated directly.
A derived class must provide definitions for all pure virtual functions of the base class. Once all pure virtual functions are defined, the derived class becomes concrete and can be instantiated.
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
// Implement the pure virtual functions from Shape
void draw() const override {
std::cout << "Drawing a circle with radius " << radius << std::endl;
}
double area() const override {
return 3.14159 * radius * radius;
}
};
In this example, the Circle
class inherits from Shape
and implements the draw()
and area()
functions, making it a concrete class that can be instantiated.
int main() {
Shape* shape = new Circle(5.0); // Polymorphic behavior
shape->draw(); // Calls Circle's draw function
std::cout << "Area: " << shape->area() << std::endl;
delete shape; // Clean up
return 0;
}
Polymorphism: Abstract base classes provide the foundation for polymorphism. You can write code that operates on pointers or references to the abstract base class, enabling flexibility in the types of objects used at runtime.
void renderShape(const Shape& shape) {
shape.draw(); // Calls the derived class' implementation
}
Code Reusability: By defining common functionality or behavior in the abstract base class and allowing derived classes to implement specific behaviors, you can create a framework for reusability.
Enforcing a Contract: Abstract base classes enforce that derived classes provide certain behavior by defining pure virtual functions. Any class derived from an abstract class must implement the abstract methods, ensuring that the derived class adheres to a certain “contract.”
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
void draw() const override {
std::cout << "Drawing a rectangle with width " << width << " and height " << height << std::endl;
}
double area() const override {
return width * height;
}
};
int main() {
Shape* shapes[] = {new Circle(3.0), new Rectangle(4.0, 5.0)};
for (int i = 0; i < 2; ++i) {
shapes[i]->draw();
std::cout << "Area: " << shapes[i]->area() << std::endl;
delete shapes[i]; // Clean up memory
}
return 0;
}
Here, we have two different classes (Circle
and Rectangle
) both inheriting from the abstract Shape
class. Both classes implement draw()
and area()
. In the main()
function, polymorphism allows the use of the Shape*
pointer to hold objects of both derived types and call their methods.
Shape s;
will cause a compile-time error.Shape*
), you can work with derived objects without needing to know their specific type.virtual ~Shape() {} // Virtual destructor
= 0
syntax and must be implemented by derived classes.