Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   Detail about How VPTR and Virtual table works (http://www.go4expert.com/articles/vptr-virtual-table-t8403/)

asadullah.ansari 22Jan2008 18:55

Detail about How VPTR and Virtual table works
 
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

shabbir 3Feb2008 12:32

Re: Detail about How VPTR and Virtual table works
 
Nominate this article for the month for January 2007

johnson.reddy 5Feb2008 17:07

Re: Detail about How VPTR and Virtual table works
 
I was really confused in virtual functions that how it's internall works. Now I got everything from your post. Thanks

mail4aisha 5Feb2008 21:21

Re: Detail about How VPTR and Virtual table works
 
Thanks Asadullah!!! very explanable and throughly about virtual pointer.

flyingfor 6Feb2008 19:56

Re: Detail about How VPTR and Virtual table works
 
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....

alramesh 6Feb2008 21:31

Re: Detail about How VPTR and Virtual table works
 
Example 10 is really excellent!!!

nileshkumar_1982 7Feb2008 11:01

Re: Detail about How VPTR and Virtual table works
 
Good one!!!

sandymalhotra 11Feb2008 16:34

Re: Detail about How VPTR and Virtual table works
 
I am new to C++. As I saw your post I fully understand the concept of VPTR, VTable etc.
******** No Issue at all. Thanks **********

sydneytech 11Feb2008 16:42

Re: Detail about How VPTR and Virtual table works
 
Really nice info of Virtual function. I was really confused with virtual function having multiple inheritance

imrantechi 13Feb2008 13:46

Re: Detail about How VPTR and Virtual table works
 
really this is an excellent article ,there was a lot of confusion in vptr

this article has really helped me understand the concept better


All times are GMT +5.5. The time now is 00:35.