Cpp Programming Abstract Classes And Interfaces Complete Guide

 Last Update:2025-06-22T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    6 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of CPP Programming Abstract Classes and Interfaces

CPP Programming: Abstract Classes and Interfaces Explained in Detail with Important Information

Abstract Classes

An abstract class in C++ is a class that cannot be instantiated on its own and must be inherited by other classes. Abstract classes typically contain pure virtual functions—functions that are declared but not defined within the abstract class. Derived classes must provide concrete implementations for all these pure virtual functions. This mechanism is used to establish a contract or a template for other classes, ensuring they have certain functionalities.

Key Features of Abstract Classes:

  • Pure Virtual Functions: These are indicated by =0 in the function declaration. Example:
    class Animal {
        virtual void makeSound() = 0;  // Pure virtual function
    };
    
  • Cannot Instantiate: You cannot create objects of an abstract class directly.
  • Purpose: To define a common interface for derived classes.

Example:

class Shape {
public:
    virtual double area() const = 0;  // Pure virtual function
    virtual void draw() const = 0;    // Pure virtual function
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    double area() const override {
        return 3.14159 * radius * radius;
    }
    void draw() const override {
        // Drawing implementation
    }
};

In this example, Shape is an abstract class because it contains pure virtual functions area() and draw(). The Circle class, an inheritor of Shape, must implement these functions.

Interfaces

In C++, an interface is typically represented by an abstract class with only pure virtual functions. Unlike languages like Java, C++ does not have a distinct keyword for interfaces; however, the concept is widely used and understood.

Key Features of Interfaces:

  • Non-Functional Members: Interfaces generally do not contain any member variables or member functions with default implementations.
  • Complete Abstraction: All methods are abstract, ensuring that any class implementing the interface must provide definitions for them.
  • Multiple Inheritance Support: Interfaces can be used to support multiple inheritance, one of the advantages over abstract classes in terms of flexibility.

Example:

class Printable {
public:
    virtual void print() const = 0;   // Pure virtual function
    virtual ~Printable() = default; // Virtual destructor to avoid slicing
};

class Loggable {
public:
    virtual void log() const = 0;     // Pure virtual function
    virtual ~Loggable() = default;  // Virtual destructor
};

class Document : public Printable, public Loggable {
public:
    void print() const override {
        // Print implementation
    }
    void log() const override {
        // Log implementation
    }
};

Here, Printable and Loggable are interfaces, and Document is a class that implements both interfaces, providing concrete definitions for all the pure virtual functions.

Important Information

  1. Virtual Destructors: In abstract classes with virtual functions, it's crucial to define a virtual destructor, even if it's empty. This prevents slicing when deleting objects through base class pointers.

    class AbstractBase {
    public:
        virtual ~AbstractBase() = default;  // Virtual destructor
        virtual void performTask() = 0;
    };
    
  2. Pure Virtual Destructors: When defining abstract classes, ensure that if you provide a definition for a pure virtual destructor, it must be inline or defined outside the class to maintain the abstract nature.

    class Interface {
    public:
        virtual void method() = 0;
        virtual ~Interface() {}  // Pure virtual destructor with a definition
    };
    
  3. Usage in Design Patterns: Abstract classes and interfaces are fundamental in implementing design patterns such as Strategy, Observer, and Factory. These components often extend abstract classes or implement interfaces to adhere to specific behaviors and operations.

  4. Memory Footprint: Abstract classes can have member variables, whereas interfaces typically do not. Therefore, classes inheriting from abstract classes may have a larger memory footprint compared to those implementing interfaces.

  5. Flexibility vs. Rigidity: While abstract classes allow for both interface and implementation, interfaces strictly enforce abstraction, leading to more rigid designs but greater flexibility in changing implementation details.

Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement CPP Programming Abstract Classes and Interfaces

Introduction

Abstract classes and interfaces in C++ are used to create blueprints for other classes to derive from, and they can contain pure virtual functions, which must be implemented by derived classes.

Step 1: Understanding Pure Virtual Functions

A pure virtual function is defined as a virtual function with no implementation and is set to 0. It makes a class abstract, meaning you cannot create an object of this class directly.

Step 2: Defining Abstract Classes

An abstract class is a class that contains at least one pure virtual function. Such classes cannot be instantiated, but they can be subclassed.

Step 3: Defining Interfaces

In C++, there is no built-in keyword like interface, but you can use abstract classes to achieve the same effect. An interface in C++ is typically a class that has only pure virtual functions, and no member variables.

Step 4: Implementing Derived Classes

Derived classes must override all pure virtual functions of the base abstract class to be instantiated.

Example 1: Abstract Class in C++

Let's start by creating an abstract class and a derived class.

#include <iostream>

// Base Abstract Class
class Shape {
public:
    virtual void draw() const = 0; // Pure virtual function
};

// Derived Concrete Class
class Circle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing Circle" << std::endl;
    }
};

// Another Derived Concrete Class
class Square : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing Square" << std::endl;
    }
};

int main() {
    // Shape shape; // This would cause a compile-time error
    Circle circle;
    Square square;

    circle.draw(); // Output: Drawing Circle
    square.draw(); // Output: Drawing Square

    return 0;
}

Explanation

  • Shape: This is an abstract class with a pure virtual function draw(). It cannot be instantiated.
  • Circle and Square: These are derived classes that implement the draw() function. They are concrete classes and can be instantiated.

Example 2: Interface in C++

Let's define an interface that resembles C# interfaces.

Top 10 Interview Questions & Answers on CPP Programming Abstract Classes and Interfaces


Top 10 Questions and Answers about CPP Programming: Abstract Classes and Interfaces

1. What are Abstract Classes in C++?

Answer: In C++, an abstract class is a class that cannot be instantiated on its own and must be inherited by other classes. An abstract class typically contains at least one pure virtual function, denoted by = 0 in its declaration. The purpose of an abstract class is to define a base template for derived classes, ensuring they implement certain methods.

Example:

class Shape {
public:
    virtual void draw() = 0; // Pure virtual function
};

In this example, Shape is an abstract class because it contains the pure virtual draw function. Any class that inherits from Shape must provide an implementation for draw to be instantiated.


2. Can an Abstract Class have Non-Virtual Functions?

Answer: Yes, an abstract class can contain non-virtual functions. These functions can provide implementations common to all derived classes or utility functions needed by the abstract class itself.

Example:

class Shape {
public:
    virtual void draw() = 0; // Pure virtual function
    void printDescription() { // Non-virtual function
        std::cout << "This is a shape." << std::endl;
    }
};

Here, printDescription is a regular (non-virtual) member function of the abstract class Shape.


3. How do you Define a Virtual Function in C++?

Answer: A virtual function in C++ is defined by using the virtual keyword before its declaration in the base class. This allows derived classes to override the base class's function.

Example:

class Base {
public:
    virtual void display() {
        std::cout << "Display from Base class." << std::endl;
    }
};

Derived classes can then override display as follows:

class Derived : public Base {
public:
    void display() override {
        std::cout << "Display from Derived class." << std::endl;
    }
};

Using override is optional but recommended for clearer code and catching mistakes.


4. Are Interfaces Available in C++ the Same as in Java?

Answer: C++ does not have dedicated "interface" types like Java, but you can achieve similar functionality using abstract classes. All functions in an interface in C++ must be pure virtual (i.e., declared with = 0) and there can't be any member variables (though static const members are allowed). However, C++ uses the term more broadly than Java to refer to any specification of operations (methods).

Example in C++:

class IShape { // Common naming convention for 'interfaces'
public:
    virtual void draw() = 0; // Pure virtual function
    virtual ~IShape() {} // Virtual destructor
};

In contrast, Java defines interfaces explicitly:

Java Example:

interface Shape {
    void draw(); // No method body
}

5. Why Use Abstract Classes?

Answer: Abstract classes are used to create a common base for multiple derived classes while enforcing certain method implementations. They're particularly useful when creating class hierarchies where the base class should define a blueprint for what subclasses can do, without being able to instantiate the base class itself.

Benefits:

  • Promotes code reuse by defining shared functionality.
  • Enforces a contract for subclasses (pure virtual functions).
  • Helps in the implementation of polymorphism.

6. Can a Constructor be Made Virtual in C++?

Answer: No, constructors cannot be made virtual in C++. The primary reason is that constructors are responsible for initializing objects, and if they were virtual, it wouldn't make sense to call a constructor through a pointer as the object wouldn't yet exist.

However, destructors should be made virtual in base classes if polymorphic behavior is desired, to ensure correct cleanup of derived objects when deleted through a base class pointer.

Example:

class Shape {
public:
    virtual ~Shape() { // Virtual destructor
        std::cout << "Shape destructor called." << std::endl;
    }
};

7. What Happens if All Functions in a Class are Pure Virtual?

Answer: If all functions in a class are pure virtual, then the class effectively becomes an interface. Such a class cannot be instantiated directly and serves only as a means for other classes to inherit from and implement its methods.

Example:

class IAnimal {
public:
    virtual void eat() = 0; // Pure virtual function
    virtual void breathe() = 0; // Pure virtual function
    virtual ~IAnimal() {} // Virtual destructor
};

Any class that inherits from IAnimal must implement eat and breathe to be instantiated.


8. Can Abstract Classes Have Data Members?

Answer: Yes, abstract classes can have data members. These can be used to store information that is relevant across different derived classes or to maintain state within the abstract class.

Example:

class Employee {
protected:
    std::string name; // Data member
    int employeeID; // Data member

public:
    virtual void calculateSalary() = 0; // Pure virtual function
    Employee(std::string n, int id) : name(n), employeeID(id) {}
};

In this example, Employee has data members name and employeeID which can be used by derived classes like Manager and Developer.


9. Does C++ Support Multiple Inheritance with Abstract Classes?

Answer: Yes, C++ supports multiple inheritance. Consequently, a class can inherit from more than one abstract class, requiring to implement all the pure virtual functions from all its abstract base classes.

Example:

class IShape {
public:
    virtual void draw() = 0; // Pure virtual function
    virtual ~IShape() {} // Virtual destructor
};

class ICircle {
public:
    virtual void rotate() = 0; // Pure virtual function
    virtual ~ICircle() {} // Virtual destructor
};

class Circle : public IShape, public ICircle {
public:
    void draw() override { // Implementing draw
        std::cout << "Drawing Circle..." << std::endl;
    }
    void rotate() override { // Implementing rotate
        std::cout << "Rotating Circle..." << std::endl;
    }
};

With multiple inheritance, the diamond problem must be managed carefully, often through virtual inheritance.

Virtual Inheritance Example:

class A {
public:
    virtual void show() = 0;
};

class B : virtual public A {};
class C : virtual public A {};

class D : public B, public C {
public:
    void show() override {
        std::cout << "Implementation of show." << std::endl;
    }
};

10. How do Abstract Classes Aid in Polymorphism?

Answer: Abstract classes facilitate polymorphism by allowing the use of base class pointers or references to refer to derived class objects. This enables dynamic method binding (run-time polymorphism), where the correct overridden method is called based on the actual object type.

Example:

class Shape {
public:
    virtual void draw() = 0; // Pure virtual function
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Circle..." << std::endl;
    }
};

class Square : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Square..." << std::endl;
    }
};

void drawShape(Shape* shape) { // Function using base class pointer
    shape->draw();
}

int main() {
    Shape* circlePtr = new Circle();
    Shape* squarePtr = new Square();

    drawShape(circlePtr); // Outputs: Drawing Circle...
    drawShape(squarePtr); // Outputs: Drawing Square...

    delete circlePtr;
    delete squarePtr;

    return 0;
}

In the above example, the drawShape function works with a Shape pointer, allowing it to draw both Circle and Square objects polymorphically.


You May Like This Related .NET Topic

Login to post a comment.