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 = ▭ 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…)
Each object (that belongs to a class with at least one virtual function) has a pointer, called a
vptr. It points to thevtblof its actual class (which each class with virtual functions has at least one of; possibly more than one for some multiple-inheritance scenarios).The
vtblcontains a bunch of pointers, one for each virtual function. So at runtime, the code just uses the object’svptrto locate thevtbl, and from there the address of the actual overridden function.In your specific case,
Polygon,Rectangle, andTriangleeach has avtbl, each with one entry pointing to its relevantareamethod. Yourppoly1will have avptrpointing toRectangle‘svtbl, andppoly2similarly withTriangle‘svtbl. Hope this helps!