Home › Forums › C Programming › Details about VPTR, Virtual table, Virtual Function
- This topic has 1 reply, 2 voices, and was last updated 16 years, 9 months ago by bharat123.
- AuthorPosts
- January 22, 2008 at 7:47 am #2061shalizyParticipant
Assumption: machine is 32-bit .
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 layout12345678910111213141516<br />class Test<br />{<br />public:<br />int data1;<br />int data2;<br />int fun1();<br />};<br />int main()<br />{<br />Test obj;<br />cout << "obj's Size = " << sizeof(obj) << endl;<br />cout << "obj 's Address = " << &obj << endl;<br />return 0;<br />}<br />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
1234567891011121314151617181920212223<br />class Test<br />{<br />public:<br />int a;<br />int b;<br />};<br />class dTest : public Test<br />{<br />public:<br />int c;<br />};<br />int main()<br />{<br />Test obj1;<br />cout << "obj1's Size = " << sizeof(obj1) << endl;<br />cout << "obj1's Address = " << &obj1 << endl;<br />dTest obj2;<br />cout << "obj2's Size = "<< sizeof(obj2) << endl;<br />cout << "obj2's Address = "<< &obj2 << endl;<br />return 0;<br />}<br />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.1234567891011121314151617<br />class Test<br />{<br />public:<br />int data;<br />virtual void fun1()<br />{<br />cout << "Test::fun1" << endl;<br />}<br />};<br />int main()<br />{<br />Test obj;<br />cout << "obj's Size = " << sizeof(obj) << endl;<br />cout << "obj's Address = " << &obj << endl;<br />return 0;<br />}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 function123456789101112131415161718<br />class Test<br />{<br />public:<br />int data;<br />virtual void fun1() { cout << "Test::fun1" << endl; }<br />virtual void fun2() { cout << "Test::fun2" << endl; }<br />virtual void fun3() { cout << "Test::fun3" << endl; }<br />virtual void fun4() { cout << "Test::fun4" << endl; }<br />};<br />int main()<br />{<br />Test obj;<br />cout << "obj's Size = " << sizeof(obj) << endl;<br />cout << "obj's Address = " << &obj << endl;<br />return 0;<br />}<br />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:123456789101112131415161718192021222324252627282930313233<br />class Test<br />{<br />public:<br />int a;<br />int b;<br />Test(int temp1 = 0, int temp2 = 0)<br />{<br />a=temp1 ;<br />b=temp2 ;<br />}<br />int getA() <br />{<br />return a;<br />}<br />int getB() <br />{<br />return b;<br />}<br />virtual ~Test();<br />};<br />int main()<br />{<br />Test obj(5, 10);<br />// Changing a and b<br />int* pInt = (int*)&obj;<br />*(pInt+0) = 100; <br />*(pInt+1) = 200; <br />cout << "a = " << obj.getA() << endl;<br />cout << "b = " << obj.getB() << endl;<br />return 0;<br />}<br />OUTPUT:
a = 200
b = 10
If we Change the code as then123456<br />// Changing a and b<br />int* pInt = (int*)&obj;<br />*(pInt+1) = 100; // In place of 0<br />*(pInt+2) = 200; // In place of 1<br />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:
12345678910111213141516<br />class Test<br />{<br />virtual void fun1()<br />{<br />cout << "Test::fun1" << endl;<br />}<br />};<br />int main()<br />{<br />Test obj;<br />cout << "VPTR's Address " << (int*)(&obj+0) << endl;<br />cout << "VPTR's Value " << (int*)*(int*)(&obj+0) << endl;<br />return 0;<br />}<br />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:1234567891011121314151617181920212223<br />#include <iostream><br />using namespace std;<br />class Test<br />{<br />virtual void fun1()<br />{<br />cout << "Test::fun1" << endl;<br />}<br />};<br />typedef void (*Fun)(void);<br />int main()<br />{<br />Test obj;<br />cout << "VPTR's Address " << (int*)(&obj+0) << endl;<br />cout << " VIRTUAL TABLE 's Address " << (int*)*(int*)(&obj+0) << endl; // Value of VPTR<br />cout << "Value at first entry of VIRTUAL TABLE " << (int*)*(int*)*(int*)(&obj+0) << endl;<br /><br />Fun pFun = (Fun)*(int*)*(int*)(&obj+0); // calling Virtual function<br />pFun();<br />return 0;<br />}<br /></iostream>OUTPUT:
VPTR’s Address 0012FF7C
VIRTUAL TABLE ‘s Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Test: fun1
Example 8:1234567891011121314151617<br />class Test<br />{<br />virtual void fun1() { cout << "Test::fun1" << endl; }<br />virtual void func1() { cout << "Test::func1" << endl; }<br />};<br />int main()<br />{<br />Test obj;<br />cout << "VPTR's Address " << (int*)(&obj+0) << endl;<br />cout << "VIRTUAL TABLE 's Address"<< (int*)*(int*)(&obj+0) << endl;<br />// Calling Virtual table functions<br />cout << "Value at 1st entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+0) << endl;<br />cout << "Value at 2nd entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+1) << endl;<br />return 0;<br />}<br />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
123456789101112131415161718192021<br />class Test<br />{<br />virtual void fun1() { cout << "Test::fun1" << endl; }<br />virtual void func1() { cout << "Test::func1" << endl; }<br />};<br />typedef void(*Fun)(void);<br />int main()<br />{<br />Test obj;<br />Fun pFun = NULL;<br /><br />// calling 1st virtual function<br />pFun = (Fun)*((int*)*(int*)(&obj+0)+0);<br />pFun();<br />// calling 2nd virtual function<br />pFun = (Fun)*((int*)*(int*)(&obj+0)+1);<br />pFun();<br />return 0;<br />}<br />OUTPUT:
Test::fun1
Test::func1
Example 10: multiple Inheritance1234567891011121314151617181920212223242526<br />class Base1<br />{<br />public:<br />virtual void fun();<br />};<br />class Base2<br />{<br />public:<br />virtual void fun();<br />};<br />class Base3<br />{<br />public:<br />virtual void fun();<br />};<br />class Derive : public Base1, public Base2, public Base3<br />{<br />};<br />int main()<br />{<br />Derive obj;<br />cout << "Derive's Size = " << sizeof(obj) << endl;<br />return 0;<br />}<br />OUTPUT:
Derive’s Size = 12Example 11: Calling Virtual Functions in case of Multiple Inheritance
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859<br />class Base1<br />{<br />virtual void fun1() { cout << "Base1::fun1()" << endl; }<br />virtual void func1() { cout << "Base1::func1()" << endl; }<br />};<br />class Base2 {<br />virtual void fun1() { cout << "Base2::fun1()" << endl; }<br />virtual void func1() { cout << "Base2::func1()" << endl; }<br />};<br />class Base3 {<br />virtual void fun1() { cout << "Base3::fun1()" << endl; }<br />virtual void func1() { cout << "Base3::func1()" << endl; }<br />};<br />class Derive : public Base1, public Base2, public Base3<br />{<br />public:<br />virtual void Fn()<br />{<br />cout << "Derive::Fn" << endl;<br />}<br />virtual void Fnc()<br />{<br />cout << "Derive::Fnc" << endl;<br />}<br />};<br />typedef void(*Fun)(void);<br />int main()<br />{<br />Derive obj;<br />Fun pFun = NULL;<br /><br />// calling 1st virtual function of Base1<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);<br />pFun();<br />// calling 2nd virtual function of Base1<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);<br />pFun();<br />// calling 1st virtual function of Base2<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);<br />pFun();<br />// calling 2nd virtual function of Base2<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);<br />pFun();<br />// calling 1st virtual function of Base3<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);<br />pFun();<br />// calling 2nd virtual function of Base3<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);<br />pFun();<br />// calling 1st virtual function of Drive<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);<br />pFun();<br />// calling 2nd virtual function of Drive<br />pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);<br />pFun();<br />return 0;<br />}<br />OUTPUT:
Base1::fun
Base1::func
Base2::fun
Base2::func
Base3::fun
Base3::func
Drive::Fn
Drive::Fncadministrator2008-01-27 11:34:41 - February 15, 2008 at 12:20 am #3322bharat123Participant
Hiin the example 10 of multiple inheritance ,i could’t understand the why the sizeof Derived class is 12 bytes, plz explain why this happening.
waiting for ur reply……………
- AuthorPosts
- The forum ‘C Programming’ is closed to new topics and replies.