Virtual Functions and Dynamic Binding in C++

A function can be implemented in several classes along the inheritance chain. Virtual functions enable the system to decide which function is invoked at runtime based on the actual type of the object.

The program in Listing 15.9 defines the displayGeometricObject function that invokes the toString function on a GeometricObject (line 10).

The displayGeometricObject function is invoked in lines 16, 19, 22 by passing an object of GeometricObject, Circle, and Rectangle, respectively. As shown in the output, the toString() function defined in class GeometricObject is invoked. Can you invoke the toString() function defined in Circle when executing display- GeometricObject(circle), the toString() function defined in Rectangle when executing displayGeometicObject(rectangle), and the toString() function defined in GeometricObject when executing displayGeometricObject(geometricO bject)? You can do so simply by declaring toString as a virtual function in the base class GeometricObject.

Suppose you replace line 15 in Listing 15.1 with the following function declaration:

virtual string toString() const;

Listing 15.10 VirtualFunctionDemoUsingPointer.cpp

However, if the object argument is passed by value, the virtual functions are not bound dynamically. As shown in Listing 15.11, even though the function is defined to be virtual, the output is the same as it would be without using the virtual function.

Listing 15.11 VirtualFunctionDemoPassByValue.cpp

1 #include <iostream>
2
#include “GeometricObject.h”
3 #include “DerivedCircle.h”
4 #include “DerivedRectangle.h”
5
6
using namespace std;
7
8
void displayGeometricObject(GeometricObject g)
9 {
10   cout << g.toString() << endl;
11 }
12
13
int main()
14 {
15    displayGeometricObject(GeometricObject());
16    displayGeometricObject(Circle(
5));
17    displayGeometricObject(Rectangle(
4, 6));
18
19   
return 0;
20 }

Note the following points regarding virtual functions:

If a function is defined virtual in a base class, it is automatically virtual in all its derived classes. The keyword virtual need not be added in the function declaration in the derived class.

Matching a function signature and binding a function implementation are two sepa­rate issues. The declared type of the variable decides which function to match at com­pile time. This is static binding. The compiler finds a matching function according to parameter type, number of parameters, and order of the parameters at compile time. A virtual function may be implemented in several derived classes. C++ dynamically binds the implementation of the function at runtime, decided by the actual class of static binding versus dynamic the object referenced by the variable. This is dynamic binding.

If a function defined in a base class needs to be redefined in its derived classes, you should define it virtual to avoid confusions and mistakes. On the other hand, if a function will not be redefined, it is more efficient not to declare it virtual, because more time and system resource are required to bind virtual functions dynamically at runtime. We call a class with a virtual function a polymorphic type

Source: Liang Y. Daniel (2013), Introduction to programming with C++, Pearson; 3rd edition.

Leave a Reply

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