Because we don't always know, what instance we will face at runtime.
For example, you have classes: SuperClass
, Subclass1
and Subclass2
, and they all have a method doACoolThing()
. The user presses a button 0
, 1
or 2
, and, depending on his input, an instance of the appropriate class is created, and its doACoolThing()
method is called.
There is no way for us (and the compiler too) to figure out what class's method will be called at runtime.
That's why such tricks require a runtime support.
A small example to illustrate an idea (P.S. don't write the code like this, it's here just to illustrate polymorphism :) ):
#include <iostream>
using namespace std;
class SuperClass
{
public:
virtual void doACoolThing();
};
void SuperClass::doACoolThing()
{
cout << "Hello from the SuperClass!" << endl;
}
class Subclass1 : public SuperClass
{
virtual void doACoolThing() override;
};
void Subclass1::doACoolThing()
{
cout << "Hello from the Subclass1" << endl;
}
class Subclass2 : public SuperClass
{
virtual void doACoolThing() override;
};
void Subclass2::doACoolThing()
{
cout << "Hello from the Subclass2" << endl;
}
int main()
{
int userInput;
cout << "Enter 0, 1 or 2: ";
cin >> userInput;
SuperClass *instance = nullptr;
switch (userInput)
{
case 0:
instance = new SuperClass();
break;
case 1:
instance = new Subclass1();
break;
case 2:
instance = new Subclass2();
break;
default:
cout << "Unknown input!";
}
if (instance)
{
instance->doACoolThing();
delete instance;
}
return 0;
}