

How virtual functions works internally using vTable and vPointer?
source link: https://thispointer.com/how-virtual-functions-works-internally-using-vtable-and-vpointer/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

In this article we will discuss that how virtual functions in C++ works internally using vTable and vPointer.
If you are not clear on what is virtual function and in which scenarios we need them, then we suggest you to go through this article first,
https://thispointer.com//when-should-i-use-virtual-functions-in-c/
virtual functions is based on run time binding. So, let’s first understand what is Binding/Linking,
Binding is a kind of mapping of a function call with the function’s definition i.e. function’s address. For example,
When we make a function call like,
obj.display();
then before its execution, it gets bonded to display() function definition i.e. function’s address, so that
while code execution, correct function should be called.
There are two types of Bindings,
Early Binding:
By Default C++ Compiler do the early binding for all function calls i.e. while linking when compiler sees a function call, then it binds that call with the particular function’s address / definition.
Dynamic Binding or Run Time Binding:
When we make a member function virtual then compiler performs run time binding for that function i.e. any call to that virtual function will not be linked to any function’s address during compile time. Actual function’s address to this call will be calculated at run time. To resolve the actual function’s address or definition at run time, C++ compiler adds some additional data structure around virtual functions i.e.
- vTable
- vPointers
What is vtable & vPointer and How C++ do run time binding using them:
vTable:
Every class that has one or more virtual member functions in it has a vTable associated with it.
vTable is a kind of function pointer array that contains the addresses all virtual functions of this class. Compiler builds this vTable at compile time.
vPointer:
Now for every object of a class that has a vTable associated with it, contains a vPointer in first 4 bytes. This vPointer points to the vTable of that class.
This vPointer will be used to find the actual function address from vTable at run rime.
Lets look at an example,
class MessageCoverter { int m_count; public: virtual std::string convert(std::string msg) { msg = "[START]" + msg + "[END]"; return msg; } virtual std::string encrypt(std::string msg) { return msg; } void displayAboutInfo() { std::cout<<"MessageCoverter Class"<<std::endl; } };
As the above class contains more than 0 virtual functions i.e. convert() and encrypt(), hence it has a vTable associated with it. vTable will look like this,
Virtual Table for MessageConverter ClassNow suppose we created three different objects for this class,
MessageCoverter * ptr1 = new MessageCoverter(); MessageCoverter * ptr2 = new MessageCoverter(); MessageCoverter * ptr3 = new MessageCoverter();
Memory layout of each of the object is as follows,
vPointer and vTable for MessageConverter classIn Every object first 4 bytes will a pointer that points to the vTable of that class. This pointer is called vPointer.
Because for virtual functions linking was not done at compile time. So, what happens when a call to virtual function is executed ,i.e.
ptr1->convert("hello");
Steps are as follows,
- vpointer hidden in first 4 bytes of the object will be fetched
- vTable of this class is accessed through the fetched vPointer
- Now from the vTable corresponding function’s address will be fetched
- Function will be executed from that function pointer
Now what happens when inheritance comes into picture i.e.
Create a Derived class from MessageCoverter i.e. NewMessageCoverter,
class NewMessageCoverter : public MessageCoverter { public: std::string convert(std::string msg) { msg = "<START> " + msg + " <END>"; return msg; } };
Once a function is declared virtual in a class then for all its derived classes that function will remain virtual. Therefore in above class NewMessageConverter even if we haven’t declared convert function virtual but it will be considered as virtual because in its base class this function is virtual.
So, there is a vTable for this new class too. vTable for this new class is,
Now when we create a object of NewMessageConverter then first 4 bytes of this object i.e. vpointer points to the vTable of this new class.
MessageConverter * pNewPtr = new NewMessageConverter();
vTable and vPointer for NewMessageConverter
vTable of the NewMessageConverter contains the function address of Derived class’s (NewMessageConverter class) convert() function.
So, if we call the function convert from pNewPtr then convert() function of Derived class is called i.e.
pNewPtr->convert("hello"); // This calls the NewMessageConverter's convert() function.
This is how everything works behind the curtain for every virtual function call.
Join a list of 2000+ Programmers for latest Tips & Tutorials
Recommend
-
9
How Swift API Availability Works Internally How Swift API Availability Works Internally September 29th, 2020 We use API availability checks all the time to provide fallbacks for users running older...
-
8
How @dynamicMemberLookup Works Internally in Swift (+ Creating Custom Swift Attributes) How @dynamicMemberLookup Works Internally in Swift (+ Creating Custom Swift Attributes) December 6, 2018 Th...
-
10
How Never Works Internally in Swift November 14, 2018 Added in Swift 3, the Never type allows you to define a method that is guar...
-
6
How CaseIterable Works Internally in Swift September 21, 2018 CaseIterable is one of my favorite features in Swift 4.2. Despite b...
-
8
StaticString, and how it works internally in Swift StaticString, and how it works internally in Swift Compiler Swift Published on 03 Aug 2021
-
14
How database indexing actually works internally?Let's start with a simple example showing why you would need indexing in a database. Suppose we have a table called costing with three column...
-
9
How AsyncSequence works internally in Swift How AsyncSequence works internally in Swift Compiler Swift Published on 20 Sep 2021 As part of my s...
-
10
Josh Posted on Oct 23 ...
-
8
Reading Time: 7 minutes What is HashMap? Basically, HashMap is one of the most popular Collection classes in java. HashMap internally uses HashTable implementation. Th...
-
13
How async/await works internally in Swift How async/await works internally in Swift Published on 28 Sep 2023 async/await in Swift was introduced with iOS 15, and...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK