C++虚函数与虚函数表

多态性可分为两类:静态多态和动态多态。函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的。

每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说,虚函数表的每一项是一个虚函数的指针。

没有虚函数的C++类,是不会有虚函数表的。

两张图:

C++虚函数与虚函数表

 

C++虚函数与虚函数表

 


简单例子:

 

复制代码
 1 #include <iostream>

 2 #include <windows.h>

 3 

 4 using namespace std;

 5 

 6 class base

 7 {

 8     virtual void f(){cout<<"base::f"<<endl;};

 9     virtual void g(){cout<<"base::g"<<endl;};

10     virtual void h(){cout<<"base::h"<<endl;};

11 };

12 

13 typedef void (*pfun)();

14 

15 void main()

16 {

17     DWORD w=0x4011e0; //虚函数表第一项的内容,也就是第一个虚函数的地址

18 

19     pfun fun=NULL;

20     base b;

21     base *pbase=&b;

22 

23     fun=(pfun)w;

24     fun();    //调用第一个虚函数

25 }
复制代码

查看对象b在内存中:

C++虚函数与虚函数表

查看虚函数表:

C++虚函数与虚函数表

 

 虚函数表的指针4个字节大小(vptr),存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

 

虚函数表的结束标志在不同的编译器下是不同的。在VC6.0下,这个值是NULL,如图:

C++虚函数与虚函数表

 

 


另一个例子:

 

复制代码
 1 #include <iostream>

 2 

 3 using namespace std;

 4 

 5 class base

 6 {

 7     virtual void f(){cout<<"base::f"<<endl;};

 8     virtual void g(){cout<<"base::g"<<endl;};

 9     virtual void h(){cout<<"base::h"<<endl;};

10 };

11 

12 class Derive : public base

13 {

14     

15 public:

16     Derive(){};

17     virtual void f() { cout << "Derive::f" << endl; }    

18     virtual void g() { cout << "Derive::g" << endl; }

19     

20 };

21 

22 typedef void(*pfun)();

23 

24 void main()

25 {

26     pfun fun=NULL;

27     Derive d;

28     base *p=&d;

29 

30     fun=(pfun)**((int**)p);

31     fun();    //调用第一个虚函数

32 

33     fun=(pfun)*(*((int**)p)+2);

34     fun();    //调用第三个函数

35 

36 }
复制代码

 

查看对象d在内存中:

C++虚函数与虚函数表

 


多重继承:

   有几个父类,就有几个vtab和vptr

 

C++虚函数与虚函数表

 

C++虚函数与虚函数表

 

代码:

复制代码
  1 #include <iostream>

  2  

  3 using namespace std;

  4  

  5 class Base1 {

  6  

  7 public:

  8  

  9             virtual void f() { cout << "Base1::f" << endl; }

 10  

 11             virtual void g() { cout << "Base1::g" << endl; }

 12  

 13             virtual void h() { cout << "Base1::h" << endl; }

 14  

 15  

 16  

 17 };

 18  

 19 class Base2 {

 20  

 21 public:

 22  

 23             virtual void f() { cout << "Base2::f" << endl; }

 24  

 25             virtual void g() { cout << "Base2::g" << endl; }

 26  

 27             virtual void h() { cout << "Base2::h" << endl; }

 28  

 29 };

 30  

 31  

 32 class Base3 {

 33  

 34 public:

 35  

 36             virtual void f() { cout << "Base3::f" << endl; }

 37  

 38             virtual void g() { cout << "Base3::g" << endl; }

 39  

 40             virtual void h() { cout << "Base3::h" << endl; }

 41  

 42 };

 43  

 44  

 45 class Derive : public Base1, public Base2, public Base3 {

 46  

 47 public:

 48  

 49             virtual void f() { cout << "Derive::f" << endl; }

 50  

 51             virtual void g1() { cout << "Derive::g1" << endl; }

 52  

 53 };

 54  

 55  

 56 typedef void(*Fun)(void);

 57  

 58 int main() 

 59 

 60 {

 61  

 62             Fun pFun = NULL;

 63  

 64             Derive d;

 65  

 66             int** pVtab = (int**)&d;

 67  

 68             //Base1's vtable

 69  

 70             //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0);

 71  

 72             pFun = (Fun)pVtab[0][0];

 73  

 74             pFun();

 75  

 76 

 77             //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1);

 78  

 79             pFun = (Fun)pVtab[0][1];

 80  

 81             pFun();

 82  

 83 

 84             //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2);

 85  

 86             pFun = (Fun)pVtab[0][2];

 87  

 88             pFun();

 89  

 90 

 91             //Derive's vtable

 92  

 93             //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3);

 94  

 95             pFun = (Fun)pVtab[0][3];

 96  

 97             pFun();

 98  

 99  

100             //The tail of the vtable

101  

102             pFun = (Fun)pVtab[0][4];

103  

104             cout<<pFun<<endl;

105  

106  

107             //Base2's vtable

108  

109             //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);

110  

111             pFun = (Fun)pVtab[1][0];

112  

113             pFun();

114  

115  

116             //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);

117  

118             pFun = (Fun)pVtab[1][1];

119  

120             pFun();

121  

122 

123             pFun = (Fun)pVtab[1][2];

124  

125             pFun(); 

126 

127  

128             //The tail of the vtable

129  

130             pFun = (Fun)pVtab[1][3];

131  

132             cout<<pFun<<endl;

133  

134  

135             //Base3's vtable

136  

137             //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);

138  

139             pFun = (Fun)pVtab[2][0];

140  

141             pFun();

142  

143  

144             //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);

145  

146             pFun = (Fun)pVtab[2][1];

147  

148             pFun();

149  

150  

151             pFun = (Fun)pVtab[2][2];

152  

153             pFun(); 

154 

155  

156             //The tail of the vtable

157  

158             pFun = (Fun)pVtab[2][3];

159  

160             cout<<pFun<<endl;

161  

162  

163             cout<<sizeof(d)<<endl;

164 

165             return 0;

166  

167 }
复制代码

你可能感兴趣的:(C++)