To do this, you need to briefly understand what polymorphism is at runtime and how it works.
If you have a class hierarchy:
class Animal { ... virtual void sayHello() { cout << "hello" << endl; } }; class Dog : public Animal { ... void sayHello() { cout << "woof!" << endl; } };
and call the method in the Dog instance, you want to be able to (() rewrite the Dog method, not Animal . You probably know why we want this, so I donβt want to explain it further.
But how can we find out at runtime that Animal* is actually Dog* ? The fact is that we do not need to know what it is, we only need to know which functions to call or better to say which function pointer to call. All pointers to functions of virtual functions are stored in a virtual table for each class. You can imagine this as a "benchmark" on which the code calls a virtual function, depending on the actual class.
This virtual table is created at compile time (the compiler writes "recommendations" to the executable file), and each instance points to one of the available virtual tables. Therefore, if you say Dog *dog = new Dog , this points to the virtual table Dog. A call like dog->sayHello() compiles into a virtual call to the virtual sayHello function in a class that is not yet specified ...
Then, at run time, a call like dog->sayHello() first searches for a specific virtual table stored in the object (the code does not know that it is a dog, just that it is Animal) and finds a pointer to the Dog::sayHello() function.
To answer your question, this mechanism is called run-time polymorphism , because we can call methods that overload this pointer (which means that they overload the type of object you are calling), while the decision is made at runtime. You can cause peer matching polymorphism, where the compiler can know a specific type of object, for example, in Dog dog; dog.sayHello() Dog dog; dog.sayHello() .