Virtual Method Table (VMT)
This is how polymorphic calls are implemented in C++.
It’s also important to understand how this works for Virtual Inheritance.
I found the best explanation here: https://pabloariasal.github.io/2017/06/10/understanding-virtual-tables/.
How Dynamic Dispatching is achieved
The 3 steps taken at run-time in order to achieve dynamic dispatch for virtual functions are:
- Locate the virtual pointer (vptr): when a call to a virtual function on an object is performed, the vptr of the object is used.
- Locate the Virtual Table (vtable): The vptr leads to the vtable of the class.
- Call the Virtual Function: The vtable contains pointers to the virtual functions for that class, which is how we can call those functions.
Notes from CS247
Though this is sometimes slightly confusing. See Virtual Method first.
For the code above, we have the following vptr and vtable layout:
When we create a vec2
or vec3
, we know what type of object we’re creating, so we can fill in the appropriate vptr for that object.
When you call v->doSomething()
, the pointer v
will be pointing to either an object of type vec2
or vec3
.
- in either case, we can simply follow the vptr of that object, get to the vtable, and find the function address for the
doSomething
method.
Warning
There is extra running time cost in the time it takes to follow the vptr and access the vtable.
There is a single virtual pointer (vptr) per object, not per virtual function.
C++ Philosophy: Don’t pay for costs unless you ask for it.
I still need to fully understand how the vtables are implemented.
Virtual Static Functions CANNOT exist
This is also why a virtual function cannot be global or static because, by definition, a virtual function is a member function of a base class and relies on a specific object to determine which implementation of the function is called.
More details here with vpointers and vtables: