Demystifying dynamic polymorphism
C++ supports a dynamic (run-time) polymorphic behavior. Polymorphism simply means: one form, many different behaviors – meaning the same line of code, can have completely different outcomes. It is done using pointers
Here I have some classes, I use struct for simplicity since all is public.
struct Car
{
virtual void start() {};
};
struct Skoda : public Car
{
virtual void start() { std::cout << "Skoda started\n"; }
};
struct Audi : public Car
{
virtual void start() { std::cout << "Audi started\n"; }
};
struct BMW : public Car
{
virtual void start() { std::cout << "BMW started\n"; } };
Notice base class Car has a simple method that is marked as virtual. Also, all other classes have functions with the same name and marked as virtual, but in their case, the word is not necessary. I put it there because it is good practice to do so. The point here is that the child classes are overriding the base class function, and to get polymorphic behavior we must mark the base class function as virtual.
Here I declare a base class pointer and derived class object - which is perfectly legal - and call the method start():
Car* some_car = new Skoda;
some_car->start();
Which method will be called?
The derived class method will be called. The Skoda will start, so the output will be "Skoda started".
Why is it so? Because I have declared the base class start() function as virtual and I overrode it in my derived class. If it was not marked as virtual, C++ would statically bind the call to the base class, and nothing would be output.
Now, let's see the polymorphism.
int main()
{
Car* some_car = new Skoda;
some_car->start();
delete some_car; // clear the memory
some_car = new Audi;
some_car->start();
delete some_car; // clear the memory
some_car = new BMW;
some_car->start();
delete some_car; // clear the memory
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// flag to check for memory leaks
return 0;
}
Here I declare a pointer of type Car what points to type Skoda – base class pointer and derived class object. I call a method start() for and after each call, the newly allocated object is explicitly destroyed with delete. The point to show here is that I call some_car->start(); three times, but each time a different start function is executed and different output I have.
Skoda started
Audi started
BMW started
Simple enough.
It is because the base class declares the start function as virtual and because I made three pointers of the same base type but each pointing to a different object. The call dynamically bound in this case.