Vtables is also known as many different names: virtual function table, virtual method table, and even as a dispatch table.
Usage of Vtables: Polymorphism
when working with virtual function in C++, it is the vtable that is being used behind the scenes to help achieve polymorphism.
What is Vtables
Whenever a class itself contains virtual functions or overrides virtual functions from a parent class, the compiler builds a vtable for that class. This means that not all classes have a vtable created for them by the compiler. The vtable contains function pointers that point to the virtual functions in that class. There can only be one vtable per class, and all objects of the same class will share the same vtable. Associated with every vtable is what is called a vpointer. The vpointer points to the vtable, it is used to access the functions inside the vtable. The vtable would be useless without a vpointer.
For any class that contains a vtable, the compiler will also add "hidden" code to the constructor of that class to initialize the vpointers of its objects to the address of the corresponding vtable. This is how "dynamic binding" works.
class Animal {
protected:
int weight;
public:
virtual int getWeight() {}; // contains a vtable
};
class Tiger : public Animal {
public:
int getWeight() { cout << "tiger's weight" << endl;}
};
int main(void) {
Tiger tiger;
/* An Animal pointer is set to point to an object of the derived Tiger class. */
Animal *animal = &tiger;
/* dynamic binding */
tiger->getWeight();
}
There can only be one vtable per class and all objects of the same class will share the same vtable. In the above example, the Animal and Tiger classes will each have their own vtable, but any objects of the Animal or Tiger classes will use their respective class's vtables. Vtables are used at runtime. In the above example, Tiger class overrides the getWeight virtual function provided in the Animal class, the compiler will construct a vtable for the Tiger class. If the Tiger class contains other non-virtual /non-override methods, their pointers will not be put inside the vtable because it is not virtual.
How Vtables are used at run time?
The question is that the code above raises is at runtime how does the cal "al->getWeight()" know to use the version of getWeight provided in the Tiger an not the Animal class. We now know that a vtable will be created for the Tiger class. And every vtable must have a vpointer that points to the vtable. Suppose, we call the vpointer that belongs to the Tiger class vptr1
Tiger tiger;
/* An Animal pointer is set to point to an object of the derived Tiger class. */
Animal *animal = &tiger;
/* dynamic binding */
tiger->getWeight();
Because the Tiger class contains a pointer to the vtable called vptr1, the call "tiger->getWeight()" will actually be translated to "(*(a1->vptr1->getWeight()))".
The object of the class containing the virtual function contains a virtual pointer that points to the base address of the virtual table in memory. Whenever there is a virtual function call, the vtable is used to resolve to the function address.