Liny_@NotePad

沉迷ACG中

通过虚函数表访问private成员

YOYO posted @ 2009年8月21日 22:25 in 【C/C++】 with tags 虚函数表 , 2547 阅读

通过虚函数表可以访问到对象的布局,通过函数指针可以运行函数,不论是private还是public,于是单继承、非virtual的demo如下:

  1. #include <iostream>
  2.  
  3. class A
  4. {
  5. public:
  6.         A(): x(5) { }
  7.  
  8. private:
  9.         virtual void fun() { std::cout << "A::fun()" << std::endl; }
  10.  
  11. private:
  12.         int x;
  13. };
  14.  
  15. class B: public A
  16. {
  17. public:
  18.         B(): y(3) { }
  19.  
  20. private:
  21.         virtual void fun() { std::cout << "B::fun()" << std::endl; }
  22.  
  23. private:
  24.         int y;
  25. };
  26.  
  27. typedef void (*Fun)();
  28.  
  29. void PrintVTable(Fun* pVT)
  30. {
  31.         Fun* pFun = pVT;
  32.         while( *pFun )
  33.         {
  34.                 (*pFun)();
  35.                 pFun ++;
  36.         }
  37. }
  38.  
  39. void PrintMembers(int* pMembers)
  40. {
  41.         std::cout << *pMembers << std::endl;
  42. }
  43.  
  44. void PrintVTableAndMembers(B* ptr)
  45. {
  46.         int* pAddress = (int*) ptr;
  47.         PrintVTable((Fun*) *pAddress);
  48.         pAddress ++;
  49.  
  50.         PrintMembers(pAddress);
  51.         pAddress ++;
  52.  
  53.         PrintMembers(pAddress);
  54.         pAddress ++;
  55. }
  56.  
  57. void main(void)
  58. {
  59.         B b;
  60.  
  61.         PrintVTableAndMembers(&b);
  62.  
  63.         system("pause");
  64. }

如果是多继承 或者 继承方式用virtual,对象的布局是不一样的,可以参考下本文:http://yoyo.is-programmer.com/posts/10671.html

附,单继承非virtual方式的访问demo:

  1. #include <iostream>
  2.  
  3. class A
  4. {
  5. public:
  6.         void f1() { std::cout << "A::f1()" << std::endl; }
  7.         void f2() { std::cout << "A::f2()" << std::endl; }
  8.  
  9.         virtual void v1() { std::cout << "A::v1()" << std::endl; }
  10.         virtual void v2() { std::cout << "A::v2()" << std::endl; }
  11.  
  12. public:
  13.         int x;
  14. };
  15.  
  16. class B: public A
  17. {
  18. public:
  19.         void f2() { std::cout << "B::f2()" << std::endl; }
  20.  
  21.         void v2() { std::cout << "B::v2()" << std::endl; }
  22.  
  23.         virtual void v3() { std::cout << "B::v3()" << std::endl; }
  24.  
  25. public:
  26.         int y;
  27. };
  28.  
  29. class C: public B
  30. {
  31. public:
  32.         void f1() { std::cout << "C::f1()" << std::endl; }
  33.         void v1() { std::cout << "C::v1()" << std::endl; }
  34.         void v3() { std::cout << "C::v3()" << std::endl; }
  35.  
  36. public:
  37.         int z;
  38. };
  39.  
  40. typedef void (*Fun)();  
  41.  
  42. void PrintVTable(A* p)
  43. {
  44.         int* pVFTable = (int*) (* ((int*)p) )//        访问虚函数表
  45.        
  46.         Fun* fun = (Fun*) pVFTable;          //   移动到第一个虚函数
  47.         int iFunSize = 0;
  48.         while( *fun )
  49.         {
  50.                 (*fun)();                     //     执行函数指针所指向的内容
  51.                 iFunSize ++;
  52.                 fun = (Fun*) (pVFTable+iFunSize);
  53.         }
  54. }
  55.  
  56. void PrintMember(A* p)
  57. {
  58.         int* pMember = (int*) p;
  59.         for (int i = 1; i<=3; i++)
  60.         {
  61.                 std::cout << (*(pMember+i)) << std::endl;
  62.         }
  63. }
  64.  
  65. void main(void)
  66. {
  67.         A* a = new C;
  68.         a->x = 10;
  69.  
  70.         PrintVTable(a);
  71.         PrintMember(a);
  72.  
  73.         C* c = (C*)a;
  74.         c->x = 100;
  75.         c->y = 80;
  76.         c->z = 50;
  77.  
  78.         PrintVTable(c);
  79.         PrintMember(c);
  80.  
  81.         system("pause");
  82. }

 

多继承非virtual方式的访问demo:

  1. #include <iostream>
  2.  
  3. class A
  4. {
  5. public:
  6.         virtual void fun(void) { std::cout << "A::fun()" << std::endl; }
  7.  
  8. public:
  9.         int x;
  10. };
  11.  
  12. class B
  13. {
  14. public:
  15.         virtual void funB(void) { std::cout << "B::funB()" << std::endl; }
  16.         virtual void funC(void) { std::cout << "B::funC()" << std::endl; }
  17.  
  18. public:
  19.         int y;
  20. };
  21.  
  22. class C: public A, public B
  23. {
  24. public:
  25.         void funC(void) { std::cout << "C::funC()" << std::endl; }
  26.  
  27. public:
  28.         int z;
  29. };
  30.  
  31. typedef void (*Fun)();
  32.  
  33. void PrintVTable(Fun* fun)
  34. {
  35.         while( *fun )
  36.         {
  37.                 (*fun)();
  38.                 fun++;
  39.         }
  40. }
  41.  
  42. void PrintMembers(int* pMember)
  43. {
  44.         std::cout << *pMember << std::endl;
  45. }
  46.  
  47. void PrintVTableAndMembers(C* c)
  48. {
  49.         int* pAddress = (int *) c;
  50.         for(int i=0; i<2; i++)
  51.         {
  52.                 PrintVTable((Fun*)*pAddress);
  53.                 pAddress ++;
  54.                 PrintMembers(pAddress);
  55.                 pAddress ++;
  56.         }
  57.         PrintMembers(pAddress);
  58. }
  59.  
  60. void main(void)
  61. {
  62.         C c;
  63.         c.x = 3;
  64.         c.y = 4;
  65.         c.z = 5;
  66.  
  67.         PrintVTableAndMembers(&c);
  68.  
  69.         system("pause");
  70. }
  1. #include <iostream>
  2.  
  3. class B1
  4. {
  5. public:
  6.         int x;
  7.  
  8. public:
  9.         void f1() { std::cout << "B1::f1()" << std::endl; };
  10.  
  11.         virtual void v1() { std::cout << "B1::v1()" << std::endl; };
  12. };
  13.  
  14. class B2
  15. {
  16. public:
  17.         int y;
  18.  
  19. public:
  20.         void f2() { std::cout << "B2::f2()" << std::endl; };
  21.  
  22.         virtual void v2() { std::cout << "B2::v2()" << std::endl; };
  23. };
  24.  
  25. class B3
  26. {
  27. public:
  28.         int z;
  29.  
  30. public:
  31.         void f3() { std::cout << "B3::f3()" << std::endl; };
  32.  
  33.         virtual void v3() { std::cout << "B3::v3()" << std::endl; };
  34. };
  35.  
  36. class D: public B1, public B2, public B3
  37. {
  38. public:
  39.         int a;
  40.  
  41. public:
  42.         virtual void v3() { std::cout << "D::v3()" << std::endl; };
  43.  
  44.         virtual void vD() { std::cout << "D::vD()" << std::endl; };
  45. };
  46.  
  47. typedef void (*Fun)();
  48.  
  49. void PrintVTable(Fun* pVT)
  50. {
  51.         while( *pVT )
  52.         {
  53.                 (*pVT) ();
  54.                 pVT++;
  55.         }
  56. }
  57.  
  58. void PrintMember(int* pMember)
  59. {
  60.         std::cout << *pMember << std::endl;
  61. }
  62.  
  63. void PrintVTableAndMembers(D* p)
  64. {
  65.         int* pRoot = (int*) p;
  66.  
  67.         for(int i=0; i<3; i++)
  68.         {
  69.                 PrintVTable((Fun*)(int *)*pRoot);
  70.                 pRoot ++;
  71.                 PrintMember(pRoot);
  72.                 pRoot ++;
  73.         }
  74.  
  75.         PrintMember(pRoot);
  76. }
  77.  
  78. void TestDynamicCast(D* d)
  79. {
  80.         std::cout << "D : " << d << std::endl;
  81.  
  82.         B1* b1 = d;
  83.         std::cout << "B1: " << b1 << std::endl;
  84.  
  85.         B2* b2 = d;
  86.         std::cout << "B2: " << b2 << std::endl;
  87.  
  88.         B3* b3 = d;
  89.         std::cout << "B3: " << b3 << std::endl;
  90. }
  91.  
  92. void main(void)
  93. {
  94.         D d;
  95.         d.a = 1;
  96.         d.x = 3;
  97.         d.y = 4;
  98.         d.z = 5;
  99.  
  100.         PrintVTableAndMembers(&d);
  101.  
  102.         TestDynamicCast(&d);
  103.  
  104.         system("pause");
  105. }

菱形继承的demo:

  1. #include <iostream>
  2.  
  3. class A
  4. {
  5. public:
  6.         void funA() { std::cout << "A::funA()" << std::endl; }
  7.  
  8.         virtual void vA() { std::cout << "A::vA()" << std::endl; }
  9.  
  10. public:
  11.         int i;
  12. };
  13.  
  14. class B: virtual public A
  15. {
  16. public:
  17.         void funB() { std::cout << "B::funB()" << std::endl; }
  18.  
  19.         virtual void vB() { std::cout << "B::vB()" << std::endl; }
  20.  
  21. public:
  22.         int x;
  23. };
  24.  
  25. class C: virtual public A
  26. {
  27. public:
  28.         void funC() { std::cout << "C::funC()" << std::endl; }
  29.  
  30.         virtual void vA() { std::cout << "C::vA()" << std::endl; }
  31.  
  32.         virtual void vC() { std::cout << "C::vC()" << std::endl; }
  33.  
  34. public:
  35.         int y;
  36. };
  37.  
  38. class D: public B, public C
  39. {
  40. public:
  41.         void funD() { std::cout << "D::funD()" << std::endl; }
  42.  
  43.         virtual void vA() { std::cout << "D::vA()" << std::endl; }
  44.  
  45.         virtual void vB() { std::cout << "D::vB()" << std::endl; }
  46.  
  47.         virtual void vD() { std::cout << "D::vD()" << std::endl; }
  48.  
  49. public:
  50.         int z;
  51. };
  52.  
  53. typedef void (*Fun)();
  54.  
  55. void PrintVTable(Fun* p)
  56. {
  57.         while( *p )
  58.         {
  59.                 (*p) ();
  60.                 p ++;
  61.         }
  62. }
  63.  
  64. void PrintMembers(int* p)
  65. {
  66.         std::cout << *p << std::endl;
  67. }
  68.  
  69. void PrintVTableAndMembers(D* d)
  70. {
  71.         int* pRoot = (int*) d;
  72.        
  73.         for(int i=0; i<2; i++)
  74.         {
  75.                 PrintVTable((Fun*) *((int*)pRoot));
  76.                 pRoot ++;
  77.                
  78.                 std::cout << "VbTable Address: " << *((int*) *pRoot) << std::endl;
  79.                 pRoot ++;
  80.  
  81.                 PrintMembers(pRoot);
  82.                 pRoot ++;
  83.         }
  84.  
  85.         PrintMembers(pRoot);
  86.         pRoot ++;
  87.        
  88.         PrintVTable((Fun*) *((int*)pRoot));
  89.         pRoot ++;
  90.  
  91.         PrintMembers(pRoot);
  92. }
  93.  
  94. void TestDynamicCast(D* d)
  95. {
  96.         std::cout << "D: " << d << std::endl;
  97.  
  98.         A* a = d;
  99.         std::cout << "A: " << a << std::endl;
  100.  
  101.         B* b = d;
  102.         std::cout << "B: " << b << std::endl;
  103.  
  104.         C* c = d;
  105.         std::cout << "C: " << c << std::endl;
  106. }
  107.  
  108. void main(void)
  109. {
  110.         D d;
  111.         d.i = 0;
  112.         d.x = 1;
  113.         d.y = 2;
  114.         d.z = 3;
  115.  
  116.         PrintVTableAndMembers(&d);
  117.  
  118.         TestDynamicCast(&d);
  119.  
  120.         system("pause");
  121. }

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter