Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6269958
  • 博文数量: 2759
  • 博客积分: 1021
  • 博客等级: 中士
  • 技术积分: 4091
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-11 14:14
文章分类

全部博文(2759)

文章存档

2019年(1)

2017年(84)

2016年(196)

2015年(204)

2014年(636)

2013年(1176)

2012年(463)

分类: C/C++

2013-10-01 11:22:57

原文地址:虚函数表实例解析 作者:HappyAndrew

 

1.     简单虚表实例

C++一个很大的特性就是多态,动态多态就是采用虚函数实现。

对于下面实例,sizeof(A)4,即一个虚表指针的大小。

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6.     virtual void vFun1(){cout<<"vFun1() is invoked"<<endl;}
  7.     virtual void vFun2(){cout<<"VFun2() is invoked"<<endl;}
  8.     virtual void vFun3(){cout<<"vFun3() is invoked"<<endl;}
  9. };

  10. typedef void (*fun)();
  11. int main()
  12. {
  13.     A a;
  14.     cout<<hex<<"(int) &a=0x"<<(unsigned int)(&a)<<endl;
  15.     cout<<hex<<"vtbl=0x"<<(unsigned int)*((unsigned int*)(&a))<<endl;
  16.     cout<<hex<<"vtbl::1stItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&a)) ))<<endl;
  17.     cout<<hex<<"vtbl::2ndItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&a))+1 ))<<endl;
  18.     cout<<hex<<"vtbl::3rdItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&a))+2 ))<<endl;
  19.     fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&a))));
  20.     Fun();
  21.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&a))+1));
  22.     Fun();
  23.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&a))+2));
  24.     Fun();

  25.     return 0;
  26. }

运行输出:




2.     函数全体覆盖(override)后的情况:



点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6.     virtual void vFun1(){cout<<"vFun1() is invoked"<<endl;}
  7.     virtual void vFun2(){cout<<"VFun2() is invoked"<<endl;}
  8.     virtual void vFun3(){cout<<"vFun3() is invoked"<<endl;}
  9. };
  10. class B:public A
  11. {
  12. public:
  13.     void vFun1(){cout<<"B::vFun1() is invoked"<<endl;}
  14.     void vFun2(){cout<<"B::VFun2() is invoked"<<endl;}
  15.     void vFun3(){cout<<"B::vFun3() is invoked"<<endl;}
  16. };

  17. typedef void (*fun)();
  18. int main()
  19. {
  20.     B b;
  21.     cout<<hex<<"(int) &a=0x"<<(unsigned int)(&b)<<endl;
  22.     cout<<hex<<"vtbl=0x"<<(unsigned int)*((unsigned int*)(&b))<<endl;
  23.     cout<<hex<<"vtbl::1stItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b)) ))<<endl;
  24.     cout<<hex<<"vtbl::2ndItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+1 ))<<endl;
  25.     cout<<hex<<"vtbl::3rdItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+2 ))<<endl;
  26.     fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))));
  27.     Fun();
  28.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+1));
  29.     Fun();
  30.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+2));
  31.     Fun();

  32.     return 0;
  33. }

实例地址(实例中存放虚表地址):

虚表内容:



0x004112b2, 0x4112a30x4112a8参见前面QuickWatch图中定义。

3.     函数部分覆盖(override)后的情况:

子类函数针覆盖虚表中父类同名同参函数的指针项,因此调用实际所指对象的函数。

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6.     virtual void vFun1(){cout<<"vFun1() is invoked"<<endl;}
  7.     virtual void vFun2(){cout<<"VFun2() is invoked"<<endl;}
  8.     virtual void vFun3(){cout<<"vFun3() is invoked"<<endl;}
  9. };
  10. class B:public A
  11. {
  12. public:
  13. //    void vFun1(){cout<<"B::vFun1() is invoked"<<endl;}
  14. //    void vFun2(){cout<<"B::VFun2() is invoked"<<endl;}
  15.     void vFun3(){cout<<"B::vFun3() is invoked"<<endl;}
  16.     virtual void vFun4(){cout<<"B::vFun4() is invoked"<<endl;}
  17. };

  18. typedef void (*fun)();
  19. int main()
  20. {
  21.     B b;
  22.     cout<<hex<<"(int) &a=0x"<<(unsigned int)(&b)<<endl;
  23.     cout<<hex<<"vtbl=0x"<<(unsigned int)*((unsigned int*)(&b))<<endl;
  24.     cout<<hex<<"vtbl::1stItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b)) ))<<endl;
  25.     cout<<hex<<"vtbl::2ndItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+1 ))<<endl;
  26.     cout<<hex<<"vtbl::3rdItem=0x"<<(unsigned int)(*( (unsigned int*)(*(unsigned int*)(&b))+2 ))<<endl;
  27.     fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))));
  28.     Fun();
  29.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+1));
  30.     Fun();
  31.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+2));
  32.     Fun();
  33.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+3));
  34.     Fun();

  35.     return 0;
  36. }





多重继承情况

多重继承会有多个虚函数表,每个基类一个虚表。

子类函数指针将覆盖基类所有虚表中的同名同参函数指针。

子类中新增的虚函数将只增加到第一个虚函数表的后面。但不能用基类指针直接访问子类新增的虚函数,编译会报错,即使用函数指针访问也会出现crash

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6.     virtual void vFun1(){cout<<"A::vFun1() is invoked"<<endl;}
  7.     virtual void vFun2(){cout<<"A::vFun2() is invoked"<<endl;}
  8.     virtual void vFun3(){cout<<"A::vFun3() is invoked"<<endl;}
  9. };
  10. class C
  11. {
  12. public:
  13.     virtual void vFun1(){cout<<"C::vFun1() is invoked"<<endl;}
  14.     virtual void vFun2(){cout<<"C::Fun2() is invoked"<<endl;}
  15. };
  16. class D
  17. {
  18. public:
  19.     virtual void vFun2(){cout<<"D::VFun2() is invoked"<<endl;}
  20.     virtual void vFun3(){cout<<"D::vFun3() is invoked"<<endl;}
  21. };
  22. class B:public A,C,D
  23. {
  24. public:
  25.     void vFun3(){cout<<"B::vFun3() is invoked"<<endl;}
  26.     virtual void vFun4(){cout<<"B::vFun4() is invoked"<<endl;}
  27. };

  28. typedef void (*fun)();
  29. int main()
  30. {
  31.     B b;
  32.     fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))));
  33.     Fun();
  34.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+1));
  35.     Fun();
  36.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+2));
  37.     Fun();
  38.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+3));
  39.     Fun();

  40.     return 0;
  41. }






5.     通过虚表中的函数指针调用基类中的私有虚函数

虽然子类实例不能直接调用基类的私有虚函数,但可以通过虚表地址直接访问基类的私有虚函数,

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. Private:
  6.     virtual void vFun1(){cout<<"A::vFun1() is invoked"<<endl;}
  7.     virtual void vFun2(){cout<<"A::vFun2() is invoked"<<endl;}
  8. public:
  9.     virtual void vFun3(){cout<<"A::vFun3() is invoked"<<endl;}
  10. };
  11. class B:public A
  12. {
  13. public:
  14. };

  15. typedef void (*fun)();
  16. int main()
  17. {
  18.     B b;
  19.     
  20.     fun Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b)))); //OK, call private A::vFun1()
  21.     Fun();
  22.     Fun=(fun)(*((unsigned int*)(*(unsigned int*)(&b))+1)); //OK, call private A::vFun2()
  23.     Fun();
  24.     b.vFun1(); //error C2248: 'A::vFun1' : cannot access private member declared in class 'A'
  25.     b.vFun3(); //OK, call public A::vFun2()
  26.     return 0;
  27. }


阅读(608) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~