Detail about How VPTR and Virtual table works

asadullah.ansari's Avatar author of Detail about How VPTR and Virtual table works
This is an article on Detail about How VPTR and Virtual table works in C++.
Rated 4.79 By 29 users
Originally written by Zeeshan Amjad

Assumption: 32-bit Machine.
Here I am going to explain How Virtual table, Virtual pointer for Virtual functions are internally working.

First we have understand memory layout.

Example 1: How the class's memory layout
Code: cpp
class Test
{
public:
    int data1;
    int data2;
    int fun1();
};

int main()
{
    Test obj;
    cout << "obj's Size = " << sizeof(obj) << endl;
    cout << "obj 's Address = " << &obj << endl;
    return 0;
}
OUTPUT:

Sobj's Size = 8
obj 's Address = 0012FF7C

Note: Any Plane member function does not take any memory.

Example 2: Memory Layout of Derived class
Code: cpp
class Test
{
public:
    int a;
    int b;
};

class dTest : public Test
{
public:
    int c;
};

int main()
{
    Test obj1;
    cout << "obj1's Size = " << sizeof(obj1) << endl;
    cout << "obj1's Address = " << &obj1 << endl;
    dTest obj2;
    cout << "obj2's Size = "<< sizeof(obj2) << endl;
    cout << "obj2's Address = "<< &obj2 << endl;
    return 0;
}
OUTPUT:
obj1's Size = 8
obj1's Address = 0012FF78
obj2's Size = 12
obj2's Address = 0012FF6C

Example 3: Memory layout If we have one virtual function.
Code: cpp
class Test
{
public:
    int data;
    virtual void fun1()
    {
        cout << "Test::fun1" << endl;
    }
};

int main()
{
    Test obj;
    cout << "obj's Size = " << sizeof(obj) << endl;
    cout << "obj's Address = " << &obj << endl;
    return 0;
}
OUTPUT:

obj's Size = 8
obj's Address = 0012FF7C

Note: Adding one virtual function in a class takes 4 Byte extra.

Example 4: More than one Virtual function

Code: cpp
class Test
{
public:
    int data;
    virtual void fun1() { cout << "Test::fun1" << endl; }
    virtual void fun2() { cout << "Test::fun2" << endl; }
    virtual void fun3() { cout << "Test::fun3" << endl; }
    virtual void fun4() { cout << "Test::fun4" << endl; }
};

int main()
{
    Test obj;
    cout << "obj's Size = " << sizeof(obj) << endl;
    cout << "obj's Address = " << &obj << endl;
    return 0;
}
OUTPUT:

obj's Size = 8
obj's Address = 0012FF7C

Note: Adding more virtual functions in a class, no extra size taking i.e. Only one machine size taking(i.e. 4 byte)

Example 5:

Code: cpp
class Test
{
public:
    int a;
    int b;
    Test(int temp1 = 0, int temp2 = 0)
    {
        a=temp1 ;
        b=temp2 ;
    }
    int getA() 
    {
        return a;
    }
    int getB() 
    {
        return b;
    }
    virtual ~Test();
};

int main()
{
    Test obj(5, 10);

    // Changing a and b
    int* pInt = (int*)&obj;
    *(pInt+0) = 100;   
    *(pInt+1) = 200;   

    cout << "a = " << obj.getA() << endl;
    cout << "b = " << obj.getB() << endl;
    return 0;
}
OUTPUT:
a = 200
b = 10

If we Change the code as then
Code: Cpp
// Changing a and b
  int* pInt = (int*)&obj;
  *(pInt+1) = 100;   // In place of 0
  *(pInt+2) = 200;   // In place of 1
 
OUTPUT:
a = 100
b = 200

Note: Who sits 1st place of Class : Answer is VPTR
VPTR - 1st placed in class and rest sits after it.

Example 6:

Code: cpp
class Test
{
    virtual void fun1()
    {
        cout << "Test::fun1" << endl;
    }
};

int main()
{
    Test obj;
    cout << "VPTR's Address " << (int*)(&obj+0) << endl;
    cout << "VPTR's Value " << (int*)*(int*)(&obj+0) << endl;
    return 0;
}
OUTPUT:

VPTR's Address 0012FF7C
VPTR's Value 0046C060

NOTE: This VPTR's value is a address of Virtual table. Lets see in next Example.

Example 7:

Code: cpp
class Test
{
    virtual void fun1()
    {
        cout << "Test::fun1" << endl;
    }
};
typedef void (*Fun)(void);

int main()
{
    Test obj;
    cout << "VPTR's Address " << (int*)(&obj+0) << endl;
    cout << " VIRTUAL TABLE 's Address " << (int*)*(int*)(&obj+0) << endl; // Value of VPTR
    cout << "Value at first entry of VIRTUAL TABLE " << (int*)*(int*)*(int*)(&obj+0) << endl;

    Fun pFun = (Fun)*(int*)*(int*)(&obj+0);   // calling Virtual function
    pFun();
    return 0;
}
OUTPUT:
VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Test: fun1


Example 8:

Code: cpp
class Test
{
    virtual void fun1() { cout << "Test::fun1" << endl; }
    virtual void func1() { cout << "Test::func1" << endl; }
};

int main()
{
    Test obj;

    cout << "VPTR's Address " << (int*)(&obj+0) << endl;
    cout << "VIRTUAL TABLE 's Address"<< (int*)*(int*)(&obj+0) << endl;

    // Calling Virtual table functions
    cout << "Value at 1st entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+0) << endl;
    cout << "Value at 2nd entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+1) << endl;

    return 0;
}
OUTPUT:

VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Value at 2nd entry of VIRTUAL TABLE 004012


Example :9

Code: cpp
class Test
{
    virtual void fun1() { cout << "Test::fun1" << endl; }
    virtual void func1() { cout << "Test::func1" << endl; }
};

typedef void(*Fun)(void);

int main()
{
    Test obj;
    Fun pFun = NULL;

    // calling 1st virtual function
    pFun = (Fun)*((int*)*(int*)(&obj+0)+0);
    pFun();

    // calling 2nd virtual function
    pFun = (Fun)*((int*)*(int*)(&obj+0)+1);
    pFun();

    return 0;
}
OUTPUT:

Test::fun1
Test::func1

Example 10: multiple Inheritance

Code: cpp
class Base1
{
public:
    virtual void fun();
};

class Base2
{
public:
    virtual void fun();
};

class Base3
{
public:
    virtual void fun();
};

class Derive : public Base1, public Base2, public Base3
{
};

int main()
{
    Derive obj;
    cout << "Derive's Size = " << sizeof(obj) << endl;
    return 0;
}
OUTPUT:

Derive's Size = 12


Example 11: Calling Virtual Functions in case of Multiple Inheritance
Code: cpp
class Base1
{
    virtual void fun1() { cout << "Base1::fun1()" << endl; }
    virtual void func1() { cout << "Base1::func1()" << endl; }
};

class Base2 {
    virtual void fun1() { cout << "Base2::fun1()" << endl; }
    virtual void func1() { cout << "Base2::func1()" << endl; }
};

class Base3 {
    virtual void fun1() { cout << "Base3::fun1()" << endl; }
    virtual void func1() { cout << "Base3::func1()" << endl; }
};

class Derive : public Base1, public Base2, public Base3
{
public:
    virtual void Fn()
    {
        cout << "Derive::Fn" << endl;
    }
    virtual void Fnc()
    {
        cout << "Derive::Fnc" << endl;
    }
};

typedef void(*Fun)(void);

int main()
{
    Derive obj;
    Fun pFun = NULL;

    // calling 1st virtual function of Base1
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
    pFun();

    // calling 2nd virtual function of Base1
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
    pFun();

    // calling 1st virtual function of Base2
    pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);
    pFun();

    // calling 2nd virtual function of Base2
    pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
    pFun();

    // calling 1st virtual function of Base3
    pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
    pFun();

    // calling 2nd virtual function of Base3
    pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);
    pFun();

    // calling 1st virtual function of Drive
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
    pFun();

    // calling 2nd virtual function of Drive
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
    pFun();

    return 0;
}
OUTPUT:

Base1::fun
Base1::func
Base2::fun
Base2::func
Base3::fun
Base3::func
Drive::Fn
Drive::Fnc
talk2mohdsaif like this
0
0
johnson.reddy's Avatar
Light Poster
I was really confused in virtual functions that how it's internall works. Now I got everything from your post. Thanks
0
mail4aisha's Avatar, Join Date: Feb 2008
Newbie Member
Thanks Asadullah!!! very explanable and throughly about virtual pointer.
0
flyingfor's Avatar
Go4Expert Member
Can you take some more complex example of virtual functions like base class' virtual function has default arguments and derived class's virtual function has no default virtual function....
0
alramesh's Avatar
Go4Expert Member
Example 10 is really excellent!!!
0
nileshkumar_1982's Avatar
Go4Expert Member
Good one!!!
0
sandymalhotra's Avatar
Light Poster
I am new to C++. As I saw your post I fully understand the concept of VPTR, VTable etc.
******** No Issue at all. Thanks **********
0
sydneytech's Avatar
Go4Expert Member
Really nice info of Virtual function. I was really confused with virtual function having multiple inheritance
0
imrantechi's Avatar, Join Date: Feb 2008
Ambitious contributor
really this is an excellent article ,there was a lot of confusion in vptr

this article has really helped me understand the concept better