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...)
Late binding or Dynamic linkage Therefore compiler determines the type of object at runtime, and then binds the function call. Virtual functions must be members of some class. Virtual functions cannot be static members. They are accessed through object pointers.
A call to a virtual function is resolved according to the underlying type of object for which it is called. A call to a nonvirtual function is resolved according to the type of the pointer or reference.
To implement virtual functions, C++ uses a special form of late binding known as the virtual table. The virtual table is a lookup table of functions used to resolve function calls in a dynamic/late binding manner.
A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.
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!
Chris Jester-Young gives the basic answer to this question.
Wikipedia has a more in depth treatment.
If you want to know the full details for how this type of thing works (and for all type of inheritance, including multiple and virtual inheritance), one of the best resources is Stan Lippman's "Inside the C++ Object Model".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With