C++ Virtual Functions

Introduction

Virtual functions in C++ allow you to achieve runtime polymorphism. They enable a base class to define a function that can be overridden by derived classes. When a base class pointer or reference points to a derived class object, the overridden function in the derived class is called. This allows you to write flexible and reusable code.

Defining and Using Virtual Functions

To declare a virtual function, you use the virtual keyword in the base class. The derived class can override this function to provide its own implementation.

Example: Basic Virtual Function

Let’s create a simple example with a base class Shape and derived classes Circle and Rectangle. Each class will have a draw function to demonstrate virtual functions.

#include <iostream>
using namespace std;

// Base class
class Shape {
public:
    // Virtual function
    virtual void draw() {
        cout << "Drawing Shape" << endl;
    }
};

// Derived class
class Circle : public Shape {
public:
    // Override the base class function
    void draw() override {
        cout << "Drawing Circle" << endl;
    }
};

// Derived class
class Rectangle : public Shape {
public:
    // Override the base class function
    void draw() override {
        cout << "Drawing Rectangle" << endl;
    }
};

int main() {
    // Create objects of derived classes
    Circle circle;
    Rectangle rectangle;

    // Create pointers of base class type
    Shape* shape1 = &circle;
    Shape* shape2 = &rectangle;

    // Call the virtual function
    shape1->draw(); // Calls Circle's draw
    shape2->draw(); // Calls Rectangle's draw

    return 0;
}

Output

Drawing Circle
Drawing Rectangle

Explanation

  • The Shape class defines a virtual function draw.
  • The Circle and Rectangle classes override the draw function.
  • In the main function, base class pointers shape1 and shape2 point to Circle and Rectangle objects, respectively.
  • When draw is called on these pointers, the overridden function in the derived class is executed.

Pure Virtual Functions and Abstract Classes

A pure virtual function is a virtual function that has no implementation in the base class and must be overridden by derived classes. A class containing at least one pure virtual function is called an abstract class, and it cannot be instantiated.

Example: Pure Virtual Function and Abstract Class

#include <iostream>
using namespace std;

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

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

// Derived class
class Rectangle : public Shape {
public:
    // Override the pure virtual function
    void draw() override {
        cout << "Drawing Rectangle" << endl;
    }
};

int main() {
    // Create objects of derived classes
    Circle circle;
    Rectangle rectangle;

    // Create pointers of base class type
    Shape* shape1 = &circle;
    Shape* shape2 = &rectangle;

    // Call the virtual function
    shape1->draw(); // Calls Circle's draw
    shape2->draw(); // Calls Rectangle's draw

    return 0;
}

Output

Drawing Circle
Drawing Rectangle

Explanation

  • The Shape class is now an abstract class with a pure virtual function draw.
  • The Circle and Rectangle classes override the draw function.
  • The main function demonstrates polymorphic behavior with base class pointers pointing to derived class objects.

Practical Examples

Example 1: Animal Sound Hierarchy

Let’s create a base class Animal with a pure virtual function makeSound. Derived classes Dog and Cat will override this function.

#include <iostream>
using namespace std;

// Abstract base class
class Animal {
public:
    // Pure virtual function
    virtual void makeSound() = 0;
};

// Derived class
class Dog : public Animal {
public:
    // Override the pure virtual function
    void makeSound() override {
        cout << "Woof Woof" << endl;
    }
};

// Derived class
class Cat : public Animal {
public:
    // Override the pure virtual function
    void makeSound() override {
        cout << "Meow Meow" << endl;
    }
};

int main() {
    // Create objects of derived classes
    Dog dog;
    Cat cat;

    // Create pointers of base class type
    Animal* animal1 = &dog;
    Animal* animal2 = &cat;

    // Call the virtual function
    animal1->makeSound(); // Calls Dog's makeSound
    animal2->makeSound(); // Calls Cat's makeSound

    return 0;
}

Output

Woof Woof
Meow Meow

Explanation

  • The Animal class is an abstract base class with a pure virtual function makeSound.
  • The Dog and Cat classes override the makeSound function.
  • The main function demonstrates polymorphic behavior with base class pointers pointing to derived class objects and calling their respective makeSound functions.

Example 2: Payment System Hierarchy

Let’s create a base class Payment with a pure virtual function processPayment. Derived classes CreditCardPayment and PayPalPayment will override this function.

#include <iostream>
using namespace std;

// Abstract base class
class Payment {
public:
    // Pure virtual function
    virtual void processPayment(double amount) = 0;
};

// Derived class
class CreditCardPayment : public Payment {
public:
    // Override the pure virtual function
    void processPayment(double amount) override {
        cout << "Processing credit card payment of $" << amount << endl;
    }
};

// Derived class
class PayPalPayment : public Payment {
public:
    // Override the pure virtual function
    void processPayment(double amount) override {
        cout << "Processing PayPal payment of $" << amount << endl;
    }
};

int main() {
    // Create objects of derived classes
    CreditCardPayment ccPayment;
    PayPalPayment ppPayment;

    // Create pointers of base class type
    Payment* payment1 = &ccPayment;
    Payment* payment2 = &ppPayment;

    // Call the virtual function
    payment1->processPayment(100.0); // Calls CreditCardPayment's processPayment
    payment2->processPayment(200.0); // Calls PayPalPayment's processPayment

    return 0;
}

Output

Processing credit card payment of $100
Processing PayPal payment of $200

Explanation

  • The Payment class is an abstract base class with a pure virtual function processPayment.
  • The CreditCardPayment and PayPalPayment classes override the processPayment function.
  • The main function demonstrates polymorphic behavior with base class pointers pointing to derived class objects and calling their respective processPayment functions.

Conclusion

Virtual functions in C++ enable runtime polymorphism, allowing derived classes to override base class functions and enabling flexible and reusable code. This chapter covered the basics of defining virtual functions, pure virtual functions, and abstract classes, with practical examples demonstrating their usage. Understanding and effectively using virtual functions is essential for writing robust and maintainable C++ programs.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top