Home › Forums › C Programming › Detail about How VPTR and Virtual table works
- This topic has 3 replies, 4 voices, and was last updated 16 years, 6 months ago by Adetutu.
- AuthorPosts
- March 10, 2008 at 1:30 am #2072shalizyParticipant
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
C++123456789101112131415class 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:
obj’s Size = 8
obj ‘s Address = 0012FF7CNote: Any Plane member function does not take any memory.
Example 2: Memory Layout of Derived class
C++1234567891011121314151617181920212223class 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 = 0012FF6CExample 3: Memory layout If we have one virtual function.
Code: cppC++1234567891011121314151617class 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 = 0012FF7CNote: Adding one virtual function in a class takes 4 Byte extra.
Example 4: More than one Virtual function
Code: cppC++1234567891011121314151617class 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 = 0012FF7CNote: 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: cppC++12345678910111213141516171819202122232425262728293031323334class 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 bint* 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 = 10If we Change the code as then
Code: Cpp // Changing a and b
C++123int* pInt = (int*)&obj;*(pInt+1) = 100; // In place of 0*(pInt+2) = 200; // In place of 1OUTPUT:
a = 100
b = 200Note: Who sits 1st place of Class : Answer is VPTR
VPTR – 1st placed in class and rest sits after it.Example 6:
Code: cppC++123456789101112131415class 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 0046C060NOTE: This VPTR’s value is a address of Virtual table. Lets see in next Example.
Example 7:
C++1234567891011121314151617181920class 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 VPTRcout << "Value at first entry of VIRTUAL TABLE " << (int*)*(int*)*(int*)(&obj+0) << endl;Fun pFun = (Fun)*(int*)*(int*)(&obj+0); // calling Virtual functionpFun();return 0;}OUTPUT:
VPTR’s Address 0012FF7C
VIRTUAL TABLE ‘s Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Test: fun1Example 8:
C++12345678910111213141516171819class 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 functionscout << "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 004012Example :9
C++1234567891011121314151617181920212223class 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 functionpFun = (Fun)*((int*)*(int*)(&obj+0)+0);pFun();// calling 2nd virtual functionpFun = (Fun)*((int*)*(int*)(&obj+0)+1);pFun();return 0;}OUTPUT:
Test::fun1
Test::func1Example 10: multiple Inheritance
C++12345678910111213141516171819202122232425262728class 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 = 12Example 11: Calling Virtual Functions in case of Multiple Inheritance
C++12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970class 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 Base1pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);pFun();// calling 2nd virtual function of Base1pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);pFun();// calling 1st virtual function of Base2pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);pFun();// calling 2nd virtual function of Base2pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);pFun();// calling 1st virtual function of Base3pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);pFun();// calling 2nd virtual function of Base3pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);pFun();// calling 1st virtual function of DrivepFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);pFun();// calling 2nd virtual function of DrivepFun = (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 - March 23, 2008 at 8:04 pm #3343deepaksanchetiParticipant
I am sorry to say…
But you r wrong at the very first example….It will simply occupy only 4 bytes…..
How come 8 bytes????? - March 31, 2008 at 12:47 am #3344valaraukarParticipant
int data1 has 4 byte
and
int data2 has 4 bytethen total 8 byte
- May 19, 2008 at 6:40 am #3345AdetutuParticipant
Hi,
Please confirm on which platform you are testing your program. On TurboC3 it has some diffrent output. I hope You are using gcc compiler on linux or solaris
- AuthorPosts
- The forum ‘C Programming’ is closed to new topics and replies.