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: 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: 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: 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: 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: 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: // 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: 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: 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: 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: 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: 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: 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
I was really confused in virtual functions that how it's internall works. Now I got everything from your post. Thanks
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....
I am new to C++. As I saw your post I fully understand the concept of VPTR, VTable etc. ******** No Issue at all. Thanks **********
Really nice info of Virtual function. I was really confused with virtual function having multiple inheritance
really this is an excellent article ,there was a lot of confusion in vptr this article has really helped me understand the concept better
Can you tell me some virtual function having default parameters and tring overriding derived from base.
You should put your queries in Queries and suggestion . By Any way You can get answer of your query in http://www.go4expert.com/showthread.php?t=8367 Thread.