Chapter 9: The Idea of Polymorphism
Another thing that we need to spend some time taking a look at is the idea of polymorphism.
This is a unique idea that is a bit different than what we are able to see with some of the other options out there, but it is going to really help us to get some good results on certain parts of our code along the way.
With this in mind, let’s take a look at how to work with polymorphism and how it is going to fit in with some of the codings that you want to work with.
To start, the word of polymorphism means that it will have many forms.
For the most part, we are going to see that polymorphism is going to occur when there is already a hierarchy of our classes in the code, and when all of these classes are going to be related, thanks to the process of inheritance that we talked about above.
C++ polymorphism means that a call to a member function is going to cause a different function to actually be executed.
The function that is going to be executed here is going to depend on the object type that would invoke the function to start with .
A good way to see how all of this polymorphism is supposed to work in our codes, we can take a look at an example.
This example below is going to show us where a base class has been derived by two other classes as well:
#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);
      }
};
// Main function for the program
int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
   // store the address of Rectangle
shape = &rec;  
   // call rectangle area.
   shape->area();
   // store the address of Triangle
   shape = &tri;
   // call triangle area.
   shape->area();
return 0;
When you have finished with compiling the code above, and you give it some time to execute, you should get the result of the parent class area there.
But both parts are going to be left blank .
The reason for this incorrect output is that the call of the function area is going to be set once by the compiler as the version that is defined in our base class.
We are able to call this the static resolution of the function call, or the static linkage.
What this means for us is that the function call is going to be fixed before we even go through and execute the program we want to work with.
This is also going to be something that we can call early binding because the area() function is set during the compilation of the program. But now we need to move in a different direction and make some small modifications to our program. In this one, we are going to precede the declaration of the area() in our Shae class with the virtual keyword.
The way that this code is going to look is below:
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;
      }
}:
After we are able to make this small modification, and then we are able to go through and compile and then execute the code again, it is going to give us a slightly different result in the process.
We are going to get the Rectangle class area and the Triangle class area instead.
With this one, the compiler is going to take a look at the contents that are in the pointer instead of its type.
Because the addresses of our objects of the rec and the tri are going to be stored in the *shape, then the respective area of our function is going to be called up here .
As you can see with this one, each of the child classes that we work with is going to have a separate implementation of our function area.
This is usually the way that we are able to work with polymorphism.
You can also come with different classes with a function of the same name, and even with the same parameters, but it is going to need to work with a different implementation to make this work.
Another thing that we are able to work with here is going to be the virtual function.
This is going to be a function that is found in a base class that can be declared with the “virtual” keyword, as we talked about above.
Defining the base class as one of these virtual functions, with the help of one of the other versions in your derived class, is going to signal to the compiler that we do not want it to work with the static linkage for this particular function at all.
What we do want to do with this one, though, is to have the selection of the function to be called up at any given point in our program, and we want it to be based on the object type that is being called .
This sort of operation is going to be known as late binding or dynamic linkage.
In addition to all of this, it is possible that you will want to go through and include your own virtual function in the base class that you work with so that it can be redefined in a derived class to help suit the objects to really suit all of the objects that are in that class.
But to make sure this works, we want to make sure that there are no meaningful definitions that you could provide to the function in the base class.
This means that we are able to take our virtual class and change it over to the base class if that works the best for our needs.