Dat is het makkelijkst uit te leggen met een voorbeeldje (in C++ code):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| class Base
{
public:
void m1();
virtual void m2();
};
class Derived : Base
{
void m1();
virtual void m2();
};
void Base::m1() { cout << "Base::m1()" << endl; }
void Base::m2() { cout << "Base::m2()" << endl; }
void Derived::m1() { cout << "Derived::m1()" << endl; }
void Derived::m2() { cout << "Derived::m2()" << endl; }
int main()
{
Derived d;
Base &b = d;
b.m1(); b.m2();
} |
Dit print, als het goed is (op typefouten e.d. na) "Base::m1()" en Derived::m2()". De niet-virtuele methode wordt statisch afgehandeld; de aan te roepen functie wordt bij het compileren vastgesteld. Dat is dus m1 van base. Wat voor waarde 'b' ook heeft, er wordt altijd Base::m1 op aangeroepen.
De functie die uitgevoerd moet worden voor m2() wordt echter at runtime bepaald (hij is dynamisch gebonden). Afhankelijk van welk object 'b' is, kan een andere methode worden geselecteerd.
Technisch gezien werkt dit niet zo ingewikkeld, vandaar dat het gebruikelijk is om binnen een OO ontwerp virtual methods te gebruiken. De compiler genereert voor elke klasse met virtuele methoden een virtual table, met daarin een rij voor elke methode en het adres van de functie die daarbij hoort. Alle objecten met virtuele methoden hebben een extra attribuut, de virtual table pointer (wat deze objecten iets, meestal 4 bytes, groter maakt dus). Bij het uitvoeren van een virtuele methode wordt niet naar een vast adres gesprongen, maar naar het adres dat in de virtual table van het huidige object staat.
Dit heeft twee implicaties: ten eerste, objecten met dynamisch gebonden methoden zijn iets groter (wat voor kleine objecten zoals bijvoorbeeld 2-dimensionale vectoren erg onwenselijk is) en het aanroepen van dynamisch gebonden methoden is iets ingewikkelder (in plaats van naar een statisch adres springen, moet de processor eerst de virtual table pointer ophalen, daar een getal bij optellen, de pointer op die locatie uit geheugen halen en daar tenslotte naar toe springen).