How does the C++ compiler know which implementation of a virtual function to call?

c++, oop, polymorphism

Solution

Each object (that belongs to a class with at least one virtual function) has a pointer, called a `vptr`. It points to the `vtbl` of its actual class (which each class with virtual functions has at least one of; possibly more than one for some multiple-inheritance scenarios).

The `vtbl` contains a bunch of pointers, one for each virtual function. So at runtime, the code just uses the object's `vptr` to locate the `vtbl`, and from there the address of the actual overridden function.

In your specific case, `Polygon`, `Rectangle`, and `Triangle` each has a `vtbl`, each with one entry pointing to its relevant `area` method. Your `ppoly1` will have a `vptr` pointing to `Rectangle`'s `vtbl`, and `ppoly2` similarly with `Triangle`'s `vtbl`. Hope this helps!

Problem

Here is an example of polymorphism from http://www.cplusplus.com/doc/tutorial/polymorphism.html (edited for readability): ``` // abstract base class #include <iostream> using namespace std; class Polygon { protected: int width; int height; public: void set_values(int a, int b) { width = a; height = b; } virtual int area(void) =0; }; class Rectangle: public Polygon { public: int area(void) { return width * height; } }; class Triangle: public Polygon { public: int area(void) { return width * height / 2; } }; int main () { Rectangle rect; Triangle trgl; Polygon * ppoly1 = &rect; Polygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; // outputs 20 cout << ppoly2->area() << endl; // outputs 10 return 0; } ``` My question is how does the compiler know that ppoly1 is a Rectangle and that ppoly2 is a Triangle, so that it can call the correct area() function? It could find that out by looking at the "Polygon * ppoly1 = ▭" line and knowing that rect is a Rectangle, but that wouldn't work in all cases, would it? What if you did something like this? ``` cout << ((Polygon *)0x12345678)->area() << endl; ``` Assuming that you're allowed to access that random area of memory. I would test this out but I can't on the computer I'm on at the moment. (I hope I'm not missing something obvious...)

Original source