How virtual functions works internally using vTable and vPointer?

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.

[showads ad=inside_post]

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 Class
Virtual Table for MessageConverter Class

Now 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 class
vPointer and vTable for MessageConverter class

In 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,

vTable for NewMessageConverter
vTable for NewMessageConverter

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.

i.e.


MessageConverter * pNewPtr = new NewMessageConverter();

vTable and vPointer for 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.

1 thought on “How virtual functions works internally using vTable and vPointer?”

  1. Thanks for the article.
    Just a missing word:
    In Every object first 4 bytes will BE a pointer that points to the vTable of that class. This pointer is called vPointer.

    ‘be’ seems to be missing.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top