Virtual Functions in C++

C++ virtual functions

Polymorphism is a key concept in object-oriented programming that refers to the ability of objects to exhibit similar behavior while still possessing unique characteristics. In simpler terms, polymorphism means “similar in form” and is a term that must be defined to fully understand object-oriented programming.

The Operator overloading and function overloading are two examples of polymorphism, where a single entity is used to refer to multiple objects or functions. Virtual functions are also a valuable tool for programming projects that require polymorphism. In this tutorial we will explore how polymorphism is utilized in object-oriented programming, including the practical applications of virtual functions.

Table of Contents

What is a Virtual Function?

Virtual functions enable redefinition of a base class function in derived classes using the “virtual” keyword. They allow dynamic selection of the appropriate function at runtime based on the object’s actual type.

Virtual functions are useful in polymorphism, which allows objects of different classes to be treated as if they are objects of the same class. This is because virtual functions enable dynamic binding, which means that the appropriate function is selected at runtime based on the actual type of the object, not just the declared type of the pointer to the object.

In C++, a virtual function can be called on a base class pointer that points to a derived class object, and the appropriate function in the derived class will be called. This is a useful feature when dealing with multiple objects of different types that share a common interface or when implementing inheritance hierarchies.

How to declare a virtual function?

#include <iostream.h>
class BaseClass {
  public: virtual void who(void) {
    cout << "Base\n";
  }
};
class Derived1: public BaseClass {
  public: void who(void) {
    cout << "Derived Class 1 \n";
  }
};

class Derived2: public BaseClass {
  public: void who(void) {
    cout << "Derived Class 2\n";
  }
};

int main(void) {
  BaseClass b;
  BaseClass * bp;
  Derived1 d1;
  Derived2 d2;

  bp = & b;
  //Executes the base class who function
  bp -> who(); 

  bp = & d1;
  //Executes the Derived1 class who function
  bp -> who(); 

  bp = & d2;
  //Executes the Derived2 class who function
  bp -> who(); 
}

Output of the C++ Program:

Base
Derived Class 1
Derived Class 2

Adding the keyword virtual

In C++, the keyword “virtual” is used to create a virtual function, which is a function that can be overridden in derived classes. When a virtual function is called on an object of a derived class, the overridden function in the derived class is called instead of the base class function.

To declare a virtual function, the keyword “virtual” is used in the function declaration in the base class. For example:

class Base {
public:
    virtual void myFunction() {
        // base class implementation
    }
};

class Derived : public Base {
public:
    void myFunction() override {
        // derived class implementation
    }
};

In this example, the function myFunction() is declared as virtual in the base class Base. The derived class Derived overrides this function by declaring it with the same name and signature, and using the override keyword to indicate that it is intended to override a virtual function in the base class.

When an object of the derived class Derived is created and the myFunction() function is called on it, the overridden function in the derived class will be called instead of the base class implementation. This is an example of dynamic polymorphism, where the appropriate function to call is determined at runtime based on the actual type of the object being used.

Using Object Pointers

In C++, an object pointer is a type of pointer that is used to store the memory address of an object. It is a variable that stores the address of an object, rather than the actual value of the object. Object pointers are essential in object-oriented programming since they enable the manipulation of objects dynamically during runtime.

To declare an object pointer, you use the class name followed by an asterisk (*), then the name of the pointer variable. For instance, to declare an object pointer to a class named “Car,” you would write:

Car *carPointer;

This declares a pointer variable named “carPointer” that can store the address of an object of type “Car.”

To assign an object’s address to the pointer variable, you use the address-of operator (&) followed by the object’s name. For example, if you have an object named “myCar,” you can assign its address to “carPointer” like this:

Car myCar;
carPointer = &myCar;

This sets the value of “carPointer” to the memory address of “myCar.”

Once you have a pointer to an object, you can access its member variables and member functions using the arrow operator (->). For example, if the “Car” class had a member function named “startEngine,” you could call it using the pointer like this:

carPointer->startEngine();

This would call the “startEngine” function on the object whose address is stored in “carPointer.”

Object pointers provide a powerful mechanism for dynamically manipulating objects in C++. Take a look at the following C++ Program.

#include <iostream.h>

class vehicle {
  int wheels;
  float weight;
  public:
    void message(void) {
      cout << "Vehicle message\n";
    }
};

class car: public vehicle {
  int passenger_load;
  public:
    void message(void) {
      cout << "Car message\n";
    }
};

class truck: public vehicle {
  int passenger_load;
  float payload;
  public:
    int passengers(void) {
      return passenger_load;
    }
};

class boat: public vehicle {
  int passenger_load;
  public:
    int passengers(void) {
      return passenger_load;
    }
  void message(void) {
    cout << "Boat message\n";
  }
};

main() {
  vehicle * unicycle;
  car * sedan;
  truck * semi;
  boat * sailboat;

  unicycle = new vehicle;
  unicycle -> message();
  sedan = new car;
  sedan -> message();
  semi = new truck;
  semi -> message();
  sailboat = new boat;
  sailboat -> message();
}

Output of the C++ Program:

Vehicle message

Car message

Vehicle message

Boat message

Th C++ Pointer Rule

A pointer declared as pointing to a base class can be used to point to an object of a derived class of that base class, but a pointer to a derived class cannot be used to point to an object of the base class or to any of the other derived classes of the base class. In our program therefore, we are allowed to declare a pointer to the vehicle class which is the base class, and use that pointer to refer to objects of either the base class or any of the derived classes.

We finally come to an example program with a virtual function that operates as a virtual function and exhibits dynamic binding or polymorphism as it is called.

#include <iostream.h>

class vehicle {
  int wheels;
  float weight;
  public:
    virtual void message(void) {
      cout << "Vehicle message\n";
    }
};

class car: public vehicle {
  int passenger_load;
  public:
    void message(void) {
      cout << "Car message\n";
    }
};

class truck: public vehicle {
  int passenger_load;
  float payload;
  public:
    int passengers(void) {
      return passenger_load;
    }
};

class boat: public vehicle {
  int passenger_load;
  public:
    int passengers(void) {
      return passenger_load;
    }
  void message(void) {
    cout << "Boat message\n";
  }
};

main() {
  vehicle * unicycle;

  unicycle = new vehicle;
  unicycle -> message();
  delete unicycle;

  unicycle = new car;
  unicycle -> message();
  delete unicycle;

  unicycle = new truck;
  unicycle -> message();
  delete unicycle;

  unicycle = new boat;
  unicycle -> message();
  delete unicycle;
}

Output of the C++ Program:

Vehicle message
Car message
Vehicle message
Boat message

C++ Dynamic Binding

Dynamic binding in C++ is a technique that allows the selection of a specific function at runtime rather than at compile-time. This is also known as late binding or runtime polymorphism. It is useful in situations where the specific function to be called cannot be determined at compile-time, such as when dealing with virtual functions.

To use dynamic binding in C++, we can define a base class with virtual functions, and then create derived classes that override those functions. We can then create objects of those derived classes and assign them to pointers of the base class type. At runtime, when a virtual function is called through the base class pointer, the appropriate derived class function is invoked.

Here’s an example program that demonstrates dynamic binding in C++:

#include <iostream>

class Shape {
public:
    virtual void draw() {
        std::cout << "Drawing a shape\n";
    }
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a circle\n";
    }
};

class Square : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a square\n";
    }
};

int main() {
    Shape* shapePtr;
    Circle circle;
    Square square;

    shapePtr = &circle;
    shapePtr->draw(); // calls Circle::draw()

    shapePtr = &square;
    shapePtr->draw(); // calls Square::draw()

    return 0;
}

In this program, we define a base class Shape with a virtual function draw(). We then define two derived classes, Circle and Square, which override the draw() function with their own implementations.

In the main() function, we create a pointer of type Shape*, which we use to point to both a Circle and a Square object. When we call the draw() function through the Shape* pointer, the appropriate derived class function is called. This demonstrates the use of dynamic binding.

In order to defined abstract classes you can use the concept of pure virtual functions. These functions have no implementation in the base class and must be implemented in derived classes. This ensures that all derived classes provide specific functionality.

M. Saqib: Saqib is Master-level Senior Software Engineer with over 14 years of experience in designing and developing large-scale software and web applications. He has more than eight years experience of leading software development teams. Saqib provides consultancy to develop software systems and web services for Fortune 500 companies. He has hands-on experience in C/C++ Java, JavaScript, PHP and .NET Technologies. Saqib owns and write contents on mycplus.com since 2004.
Related Post