Chapter Nine: Polymorphism in C++
Polymorphism is a concept in C++ which allows classes to have multiple forms. This only occurs when you have numerous classes in the code related through inheritance. Polymorphism in C++ means that the object determines the type of function to be executed by the compiler. When you call a function within a class, the compiler will look at the object type being used as an argument or parameter in the function before it invokes the function relevant to the object. In the example, we will look at how we can derive a base class based on two other classes.
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0){
width = a;
height = b;
}
int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape {
public :
Rectangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape {
public:
Triangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// This is the main function of the program
int main() {
Shape *shape;
Rectangle rec(10,7);
Triangle  tri(10,5);
// The variable shape is used to store the values for the rectangle
shape = &rec;
// This statement is used to call the function to calculate the area of the rectangle
shape->area();
// The variable shape is used to store the values for the triangl e
shape = &tri;
// This statement is used to call the function to calculate the area of the triangle
shape->area();
return 0;
}
When the above code is run, the following is the output you will receive on your screen:
Parent class area :
Parent class area :
This is not the output we want. If you are unable to identify the reason for this incorrect output, let me tell you what change needs to be made to the code. Look at how the function area() is being called. We have defined this function in the base class, and the compiler uses this version. This method of linking functions is termed as static linkage or resolution. The call of this function should be fixed before you execute the program. This process is termed early binding. The compiler will set this function when it debugs the program. Let us now make a slight change to the above program. We will declare the area function within the Shape class itself. We will also use the virtual keyword. The updated code is as follows:
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0) {
width = a;
height = b ;
}
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
When you make this modification to the code, you will receive the following output:
Rectangle class area
Triangle class area
The compiler will now look at the pointer and the contents of the variable it is pointing to. It will no longer look at the data type. The compiler calls the area function since the rec and tri class objects are not stored in shape but stored in *shape. Every child class in the above code has its own implementation of the area function. This is how programmers use the polymorphism concept in C++. The above code has different classes, and each class has the same function. The functions also take the same parameters, but the implementation of the function is different in each case.
Understanding Virtual Functions
When you define a function using the virtual keyword, it becomes a virtual function. C++ allows you to define a virtual function in the base class and a different version of the virtual function in the derived class. This only signals to the compiler that you do not want any link to exist between the functions. The only thing you need to be aware of is the position of the function you want to call in the code. To do this, you need to ensure the function selected by the compiler is based on the object you want to use it on. This type of connection or link is termed as late binding or dynamic linkage.
Pure Virtual Functions
You can include virtual functions in the base class and use that in a derived class. It is important to note that these functions can be redefined in the derived classes, so the functions suit the objects present in the derived class. There is, however, no meaningful definition you can give the function in the class. The following example shows you how you can change a virtual function in the base class.
class Shape {
protected:
int width, height;
public:
Shape(int a = 0, int b = 0) {
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
We see that the virtual function area() has been assigned the value zero in the above code. This indicates to the compiler that the function does not have a body. This is an example of a pure virtual function.