vtable和vptr

来源:互联网 发布:rose only和beast 知乎 编辑:程序博客网 时间:2024/05/18 06:27

http://www.dreamincode.net/forums/topic/45816-detail-about-how-vptr-and-virtual-table-works/

 

这是一个相当牛的帖子。

1. vptr每个对象都会有一个,而vtable是每个类有一个

2. vptr指向了vtable

3. 在C++中,如果一个类有虚函数,那么这个对象的memory layout中就有特个vptr,且在最前面

4. 一个类中就算有多个虚函数,也只有一个vptr

5. 做多重继承,就是继承了多个父类时,就会有多个vptr

6. 看最后一个例子,当子类继承了多个父类,且自己又新加了虚函数,这个vptr是借用了第一个父类的?

 

 

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 layout

view sourceprint?
01class Test
02{
03  public:
04    int data1;
05    int data2;
06    int fun1();
07};
08 
09int main()
10{
11  Test obj;
12  cout << "obj's Size = " << sizeof(obj) << endl;
13  cout << "obj 's Address = " << &obj << endl;
14  return 0;
15}


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

view sourceprint?
01class Test
02{
03public:
04  int a;
05  int b;
06};
07 
08class dTest : public Test
09{
10public:
11  int c;
12};
13 
14int main()
15{
16  Test obj1;
17  cout << "obj1's Size = " << sizeof(obj1) << endl;
18  cout << "obj1's Address = " << &obj1 << endl;
19  dTest obj2;
20  cout << "obj2's Size = "<< sizeof(obj2) << endl;
21  cout << "obj2's Address = "<< &obj2 << endl;
22  return 0;
23}


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.

view sourceprint?
01class Test
02{
03public:
04  int data;
05  virtual void fun1()
06  {
07    cout << "Test::fun1" << endl;
08  }
09};
10 
11int main()
12{
13  Test obj;
14  cout << "obj's Size = " << sizeof(obj) << endl;
15  cout << "obj's Address = " << &obj << endl;
16  return 0;
17}


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

view sourceprint?
01class Test
02{
03public:
04  int data;
05  virtual void fun1() { cout << "Test::fun1" << endl; }
06  virtual void fun2() { cout << "Test::fun2" << endl; }
07  virtual void fun3() { cout << "Test::fun3" << endl; }
08  virtual void fun4() { cout << "Test::fun4" << endl; }
09};
10 
11int main()
12 {
13  Test obj;
14  cout << "obj's Size = " << sizeof(obj) << endl;
15  cout << "obj's Address = " << &obj << endl;
16  return 0;
17 }


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:

view sourceprint?
01class Test
02 {
03public:
04  int a;
05  int b;
06  Test(int temp1 = 0, int temp2 = 0)
07  {
08     a=temp1;
09     b=temp2;
10  }
11  int getA() 
12  {
13     return a;
14  }
15  int getB() 
16  {
17     return b;
18  }
19  virtual ~Test();
20};
21 
22int main()
23{
24  Test obj(5, 10);
25 
26// Changing a and b
27  int* pInt = (int*)&obj;
28  *(pInt+0) = 100;  
29  *(pInt+1) = 200;  
30 
31  cout << "a = " << obj.getA() << endl;
32  cout << "b = " << obj.getB() << endl;
33  return 0;
34}


OUTPUT:
a = 200
b = 10

If we Change the code as then

// 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:

view sourceprint?
01class Test
02{
03  virtual void fun1()
04  {
05     cout << "Test::fun1" << endl;
06  }
07};
08 
09int main()
10{
11  Test obj;
12  cout << "VPTR's Address " << (int*)(&obj+0) << endl;
13  cout << "VPTR's Value " << (int*)*(int*)(&obj+0) << endl;
14  return 0;
15}


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:

view sourceprint?
01#include <iostream>
02using namespace std;
03 
04class Test
05 {
06   virtual void fun1()
07   {
08    cout << "Test::fun1" << endl;
09   }
10};
11typedef void (*Fun)(void);
12 
13int main()
14{
15  Test obj;
16  cout << "VPTR's Address " << (int*)(&obj+0) << endl;
17  cout << " VIRTUAL TABLE 's Address " << (int*)*(int*)(&obj+0) << endl; // Value of VPTR
18  cout << "Value at first entry of VIRTUAL TABLE " << (int*)*(int*)*(int*)(&obj+0) << endl;
19   
20  Fun pFun = (Fun)*(int*)*(int*)(&obj+0);   // calling Virtual function
21  pFun();
22  return 0;
23}


OUTPUT:
VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Test: fun1


Example 8:

view sourceprint?
01class Test
02{
03  virtual void fun1() { cout << "Test::fun1" << endl; }
04  virtual void func1() { cout << "Test::func1" << endl; }
05};
06 
07int main()
08 {
09  Test obj;
10 
11  cout << "VPTR's Address " << (int*)(&obj+0) << endl;
12  cout << "VIRTUAL TABLE 's Address"<< (int*)*(int*)(&obj+0) << endl;
13 
14  // Calling Virtual table functions
15  cout << "Value at 1st entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+0) << endl;
16  cout << "Value at 2nd entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+1) << endl;
17 
18  return 0;
19}


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

view sourceprint?
01class Test
02{
03  virtual void fun1() { cout << "Test::fun1" << endl; }
04  virtual void func1() { cout << "Test::func1" << endl; }
05};
06 
07typedef void(*Fun)(void);
08 
09int main()
10{
11  Test obj;
12  Fun pFun = NULL;
13   
14  // calling 1st virtual function
15  pFun = (Fun)*((int*)*(int*)(&obj+0)+0);
16  pFun();
17 
18  // calling 2nd virtual function
19  pFun = (Fun)*((int*)*(int*)(&obj+0)+1);
20  pFun();
21 
22  return 0;
23}


OUTPUT:

Test::fun1
Test::func1

Example 10: multiple Inheritance

view sourceprint?
01class Base1
02{
03public:
04  virtual void fun();
05};
06 
07class Base2
08{
09public:
10  virtual void fun();
11};
12 
13class Base3
14{
15public:
16  virtual void fun();
17};
18 
19class Derive : public Base1, public Base2, public Base3
20{
21};
22 
23int main()
24{
25  Derive obj;
26  cout << "Derive's Size = " << sizeof(obj) << endl;
27  return 0;
28}


OUTPUT:

Derive's Size = 12


Example 11: Calling Virtual Functions in case of Multiple Inheritance

view sourceprint?
01class Base1
02{
03  virtual void fun1() { cout << "Base1::fun1()" << endl; }
04  virtual void func1() { cout << "Base1::func1()" << endl; }
05};
06 
07class Base2 {
08  virtual void fun1() { cout << "Base2::fun1()" << endl; }
09  virtual void func1() { cout << "Base2::func1()" << endl; }
10};
11 
12class Base3 {
13  virtual void fun1() { cout << "Base3::fun1()" << endl; }
14  virtual void func1() { cout << "Base3::func1()" << endl; }
15};
16 
17class Derive : public Base1, public Base2, public Base3
18{
19public:
20  virtual void Fn()
21  {
22  cout << "Derive::Fn" << endl;
23  }
24  virtual void Fnc()
25  {
26  cout << "Derive::Fnc" << endl;
27  }
28};
29 
30typedef void(*Fun)(void);
31 
32int main()
33{
34  Derive obj;
35  Fun pFun = NULL;
36   
37  // calling 1st virtual function of Base1
38  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
39  pFun();
40 
41  // calling 2nd virtual function of Base1
42  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
43  pFun();
44 
45  // calling 1st virtual function of Base2
46  pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);
47  pFun();
48 
49  // calling 2nd virtual function of Base2
50  pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
51  pFun();
52 
53  // calling 1st virtual function of Base3
54  pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
55  pFun();
56 
57  // calling 2nd virtual function of Base3
58  pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);
59  pFun();
60 
61  // calling 1st virtual function of Drive
62  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
63  pFun();
64 
65  // calling 2nd virtual function of Drive
66  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
67  pFun();
68 
69  return 0;
70}


OUTPUT:

Base1::fun
Base1::func
Base2::fun
Base2::func
Base3::fun
Base3::func
Drive::Fn
Drive::Fnc


By
Asadullah Ansari

 

原创粉丝点击