C++ Abstract Class and Pure Virtual Function


Introduction

In C++, an abstract class is a class that cannot be instantiated directly. It serves as a base for other classes and is typically used to define a common interface for derived classes. The abstract class may contain pure virtual functions, which are functions declared in the base class but are not implemented. Derived classes are required to override these pure virtual functions to provide their own specific implementations.

Abstract classes and pure virtual functions are crucial concepts in object-oriented programming (OOP), helping to define a contract for derived classes and enabling polymorphism.


1. What is an Abstract Class?

An abstract class in C++ is a class that cannot be instantiated on its own. It is designed to be inherited by other classes that provide specific implementations of the abstract class's pure virtual functions.

  • An abstract class can have:
    • Member variables.
    • Regular functions (functions with implementations).
    • Pure virtual functions (functions without implementations).
  • An abstract class cannot be instantiated directly. It requires derived classes to implement the pure virtual functions before instances of the derived classes can be created.

Syntax to Declare an Abstract Class

class AbstractClass {
public:
    virtual void someFunction() = 0;  // Pure virtual function
};
  • = 0 after the function declaration makes it a pure virtual function.
  • This makes the class abstract, meaning no object of this class can be created directly.

2. What is a Pure Virtual Function?

A pure virtual function is a function that is declared in the base class but does not have any implementation. It forces derived classes to provide an implementation for that function. A class containing at least one pure virtual function is called an abstract class.

Syntax to Declare a Pure Virtual Function:

class Base {
public:
    virtual void functionName() = 0;  // Pure virtual function
};
  • The = 0 syntax after the function declaration marks it as a pure virtual function.
  • A class containing one or more pure virtual functions cannot be instantiated.

3. Example of Abstract Class and Pure Virtual Function

Let’s look at a basic example to understand how an abstract class and pure virtual functions work in C++.

#include <iostream>
using namespace std;

// Abstract class with pure virtual function
class Shape {
public:
    // Pure virtual function
    virtual void draw() = 0;  // No implementation, forcing derived classes to provide one
    
    // A regular function
    void display() {
        cout << "This is a shape." << endl;
    }
};

// Derived class implementing the pure virtual function
class Circle : public Shape {
public:
    void draw() override {  // Overriding the pure virtual function
        cout << "Drawing a circle!" << endl;
    }
};

// Another derived class implementing the pure virtual function
class Square : public Shape {
public:
    void draw() override {  // Overriding the pure virtual function
        cout << "Drawing a square!" << endl;
    }
};

int main() {
    // Shape shape;  // Error: cannot instantiate an abstract class

    Shape* shape1 = new Circle();  // Create a Circle object using Shape pointer
    Shape* shape2 = new Square();  // Create a Square object using Shape pointer
    
    shape1->draw();  // Output: Drawing a circle!
    shape2->draw();  // Output: Drawing a square!

    delete shape1;
    delete shape2;

    return 0;
}

Explanation:

  • The Shape class is an abstract class because it contains a pure virtual function draw(). This forces any derived class to implement the draw() function.
  • The Circle and Square classes override the draw() function, providing their own specific implementations.
  • You cannot create an instance of Shape directly, but you can create pointers to Shape and assign them to objects of derived classes (Circle and Square).
  • At runtime, the correct draw() function is called based on the actual object type, demonstrating polymorphism.

4. Why Use Abstract Classes and Pure Virtual Functions?

  1. Enforcing a Common Interface:

    • Abstract classes define a common interface for all derived classes. This ensures that derived classes implement certain functions, providing a consistent API for interacting with objects of different types.
  2. Code Reusability:

    • By defining common behavior (such as regular functions) in the abstract class, you can avoid duplicating code in derived classes. Derived classes only need to implement the specific behavior that is unique to them.
  3. Polymorphism:

    • Abstract classes and pure virtual functions enable runtime polymorphism. By using pointers or references to the base class, you can call the appropriate function for the actual object type, even if the object is referenced via a base class pointer.
  4. Separation of Interface and Implementation:

    • An abstract class allows you to separate the interface (function signatures) from the implementation (actual code), making the system more flexible and maintainable.

5. Abstract Classes and Multiple Inheritance

In C++, a derived class can inherit from multiple abstract classes. If any of the base classes contains pure virtual functions, the derived class must implement those functions.

Example of Multiple Inheritance with Abstract Classes:

#include <iostream>
using namespace std;

// First abstract class
class Printable {
public:
    virtual void print() = 0;  // Pure virtual function
};

// Second abstract class
class Scannable {
public:
    virtual void scan() = 0;  // Pure virtual function
};

// Derived class inheriting from both abstract classes
class MultiFunctionPrinter : public Printable, public Scannable {
public:
    void print() override {
        cout << "Printing document." << endl;
    }

    void scan() override {
        cout << "Scanning document." << endl;
    }
};

int main() {
    MultiFunctionPrinter mfp;
    mfp.print();  // Output: Printing document.
    mfp.scan();   // Output: Scanning document.

    return 0;
}

Explanation:

  • Printable and Scannable are two abstract classes, each with a pure virtual function (print() and scan() respectively).
  • MultiFunctionPrinter inherits from both abstract classes and provides implementations for both print() and scan().
  • Multiple inheritance allows the derived class to implement multiple interfaces (in this case, printing and scanning) through pure virtual functions.

6. Key Points about Abstract Classes and Pure Virtual Functions

  • Abstract Class: A class containing at least one pure virtual function. It cannot be instantiated directly.
  • Pure Virtual Function: A function in the base class that has no implementation and must be implemented by derived classes.
  • Use Case: Abstract classes are used when you want to define a common interface that different derived classes must adhere to, allowing for polymorphism and flexible code.
  • Inheritance: Derived classes must provide implementations for all pure virtual functions to be instantiated.