当前位置:   article > 正文

c++虚函数表、地址详解_虚函数表存在什么位置

虚函数表存在什么位置

一.什么是虚函数表,它有什么特点?

虚函数大家都知道是基本用于实现多态的,当父类指针指向子类对象的时候,如何确定调用的函数是父类里的还是子类里面的,这就要用到虚函数表。下面一点点表诉什么是虚函数表,和虚函数表的特点。如有说错的地方,欢迎指正:

1.编译器会为每个有虚函数的类创建一个虚函数表

如有类中没有虚函数,那么这个虚函数表就不存在,而不是表中无数据。同时,所有类都会有自己的虚函数表,一个类不会有另外一个类的虚函数表,包括两个类属于继承关系。

2.虚函数表会被一个类的所有对象所拥有

类的每个虚函数成员占据虚函数表的一行,所以说,如果类中有N个虚函数,那么该虚函数表将会有N*4的大小。并不是每个类对象都会有自己的表。

3.编译器会将虚函数表指针存放在类对象最前面的位置

对于类的每个对象,编译器都会为其生成一个透明不可见的指针,这个指针就是虚函数表指针,存放在该对象内存的最前位置。例如:一个类拥有虚函数表,类对象内存布局中前4个字节就是虚函数表的地址(32位)。这个接下来我们会进行测试。

4.延伸,由第一条可知,子类继承父类,其虚函数表和表函数地址是不一样的。
5.父类指针指向子类时,调用时实际上是根据子类的虚函数表进行查找

二、测试

测试内容:
虚函数表地址和虚函数地址存放位置?
多个类对象的虚函数表地址是否一样?
测试类中无虚函数,是否存在虚函数表?
子类继承父类虚函数表地址分别是什么位置?
子类重写父类中虚函数或子类重定义父类虚函数虚函数表是否发生改变?
子类指针指向父类虚函数表是什么样子?

1.测试虚函数表地址和虚函数地址

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Father
  6. {
  7. virtual void FatherFun1() {cout << "FatherFun1" <<endl;}
  8. virtual void FatherFun2() {cout << "FatherFun2" <<endl;}
  9. virtual void FatherFun3() {cout << "FatherFun3" <<endl;}
  10. };
  11. typedef void (*Fun)(void);
  12. int main()
  13. {
  14. Father father;
  15. cout << "类对象地址:" << &father << endl;
  16. cout << "虚函数表地址: " << (int*)*(int*)&father << endl;
  17. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father << endl;
  18. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father + 1 << endl;
  19. cout << "虚函数FatherFun3地址:" <<(int*)*(int*)&father + 2 << endl;
  20. cout << "测试地址是否正确" << endl;
  21. Fun fun = (Fun)*(int*)*(int*)&father;
  22. fun();
  23. fun = (Fun)*((int*)*(int*)(&father) + 1);
  24. fun();
  25. fun = (Fun)*((int*)*(int*)(&father) + 2);
  26. fun();
  27. system("pause");
  28. }

上面说过类对象内存中前4个字节就是虚函数表的地址,那么我们获取类对象前4个字节,(int)&father就是虚函数表地址,我们再给他转换成地址指针为(int*)(int)&father。

然后我们在看一下输出结果:

  1. 类对象地址:003BF90C
  2. 虚函数表地址: 00867898
  3. 虚函数FatherFun1地址:00867898
  4. 虚函数FatherFun2地址:0086789C
  5. 虚函数FatherFun3地址:008678A0
  6. 测试地址是否正确
  7. FatherFun1
  8. FatherFun2
  9. FatherFun3
  10. 请按任意键继续. . .

从这个输出我们可以看到,FatherFun1、FatherFun2、FatherFun3的地址只差了4个字节,且输出是正确的,那么第三点已确认

2.多个类对象的虚函数表地址

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Father
  6. {
  7. virtual void FatherFun1() {cout << "FatherFun1" <<endl;}
  8. virtual void FatherFun2() {cout << "FatherFun2" <<endl;}
  9. virtual void FatherFun3() {cout << "FatherFun3" <<endl;}
  10. };
  11. typedef void (*Fun)(void);
  12. int main()
  13. {
  14. Father father;
  15. cout << "类对象地址:" << &father << endl;
  16. cout << "虚函数表地址: " << (int*)*(int*)&father << endl;
  17. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father << endl;
  18. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father + 1 << endl;
  19. cout << "虚函数FatherFun3地址:" <<(int*)*(int*)&father + 2 << endl;
  20. cout << "第二个类对象" << endl;
  21. Father father1;
  22. cout << "类对象地址:" << &father1 << endl;
  23. cout << "虚函数表地址: " << (int*)*(int*)&father1 << endl;
  24. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father1 << endl;
  25. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father1 + 1 << endl;
  26. cout << "虚函数FatherFun3地址:" <<(int*)*(int*)&father1 + 2 << endl;
  27. system("pause");
  28. }

定义了两个对象,分别看两个对象的虚函数表地址是否正确,发现两个类对象虚函数表地址相同。

以下为输出:

  1. 类对象地址:0020F9C8
  2. 虚函数表地址: 00B37894
  3. 虚函数FatherFun1地址:00B37894
  4. 虚函数FatherFun2地址:00B37898
  5. 虚函数FatherFun3地址:00B3789C
  6. 第二个类对象
  7. 类对象地址:0020F9BC
  8. 虚函数表地址: 00B37894
  9. 虚函数FatherFun1地址:00B37894
  10. 虚函数FatherFun2地址:00B37898
  11. 虚函数FatherFun3地址:00B3789C
  12. 请按任意键继续. . .

由此可见,第二点现在已经确认

3.测试类中无虚函数,是否存在虚函数表

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Test
  6. {
  7. void TestFun1() {cout << "TestFun1" <<endl;}
  8. void TestFun2() {cout << "TestFun2" <<endl;}
  9. void TestFun3() {cout << "TestFun3" <<endl;}
  10. };
  11. typedef void (*Fun)(void);
  12. int main()
  13. {
  14. Test test;
  15. cout << "类对象地址:" << &test << endl;
  16. cout << "虚函数表地址: " << (int*)*(int*)&test << endl;
  17. cout << "虚函数TestFun1地址:" <<(int*)*(int*)&test << endl;
  18. cout << "虚函数TestFun2地址:" <<(int*)*(int*)&test + 1 << endl;
  19. cout << "虚函数TestFun3地址:" <<(int*)*(int*)&test + 2 << endl;
  20. system("pause");
  21. }

以下为输出:

  1. 类对象地址:0041FCEB
  2. 虚函数表地址: CCCCCCCC
  3. 虚函数TestFun1地址:CCCCCCCC
  4. 虚函数TestFun2地址:CCCCCCD0
  5. 虚函数TestFun3地址:CCCCCCD4
  6. 请按任意键继续. . .

由此可见虚函数表地址为错误,第一条确认

4.子类继承父类,但不继承虚函数表

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Father
  6. {
  7. virtual void FatherFun1() {cout << "FatherFun1" <<endl;}
  8. virtual void FatherFun2() {cout << "FatherFun2" <<endl;}
  9. virtual void FatherFun3() {cout << "FatherFun3" <<endl;}
  10. };
  11. class Son : public Father
  12. {
  13. virtual void SonFun1() {cout << "SonFun1" <<endl;}
  14. virtual void SonFun2() {cout << "SonFun2" <<endl;}
  15. virtual void SonFun3() {cout << "SonFun3" <<endl;}
  16. };
  17. typedef void (*Fun)(void);
  18. int main()
  19. {
  20. Father father;
  21. cout << "类对象地址:" << &father << endl;
  22. cout << "虚函数表地址: " << (int*)*(int*)&father << endl;
  23. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father << endl;
  24. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father + 1 << endl;
  25. cout << "虚函数FatherFun3地址:" <<(int*)*(int*)&father + 2 << endl;
  26. //cout << "虚函数sonFun1地址:" <<(int*)*(int*)&father + 3 << endl;
  27. //cout << "虚函数sonFun2地址:" <<(int*)*(int*)&father + 4 << endl;
  28. //cout << "虚函数sonFun3地址:" <<(int*)*(int*)&father + 5 << endl;
  29. Fun fun = (Fun)*(int*)*(int*)&father;
  30. fun();
  31. fun = (Fun)*((int*)*(int*)(&father) + 1);
  32. fun();
  33. fun = (Fun)*((int*)*(int*)(&father) + 2);
  34. fun();
  35. //fun = (Fun)*((int*)*(int*)(&father) + 3);
  36. //fun();
  37. //fun = (Fun)*((int*)*(int*)(&father) + 4);
  38. //fun();
  39. //fun = (Fun)*((int*)*(int*)(&father) + 5);
  40. //fun();
  41. cout << "----------------测试子类------------------" << endl;
  42. Son son;
  43. cout << "类对象地址:" << &son << endl;
  44. cout << "虚函数表地址: " << (int*)*(int*)&son << endl;
  45. cout << "虚函数继承FatherFun1地址:" <<(int*)*(int*)&son << endl;
  46. cout << "虚函数继承FatherFun2地址:" <<(int*)*(int*)&son + 1 << endl;
  47. cout << "虚函数继承FatherFun3地址:" <<(int*)*(int*)&son + 2 << endl;
  48. cout << "虚函数sonFun1地址:" <<(int*)*(int*)&son + 3 << endl;
  49. cout << "虚函数sonFun2地址:" <<(int*)*(int*)&son + 4 << endl;
  50. cout << "虚函数sonFun3地址:" <<(int*)*(int*)&son + 5 << endl;
  51. fun = (Fun)*(int*)*(int*)&son;
  52. fun();
  53. fun = (Fun)*((int*)*(int*)(&son) + 1);
  54. fun();
  55. fun = (Fun)*((int*)*(int*)(&son) + 2);
  56. fun();
  57. fun = (Fun)*((int*)*(int*)(&son) + 3);
  58. fun();
  59. fun = (Fun)*((int*)*(int*)(&son) + 4);
  60. fun();
  61. fun = (Fun)*((int*)*(int*)(&son) + 5);
  62. fun();
  63. system("pause");
  64. }

如果将代码中注释代码给恢复,会直接发生段错误。

以下为输出结果:

类对象地址:0027FCA8
虚函数表地址: 01317930
虚函数FatherFun1地址:01317930
虚函数FatherFun2地址:01317934
虚函数FatherFun3地址:01317938
FatherFun1
FatherFun2
FatherFun3
----------------测试子类------------------
类对象地址:0027FC90
虚函数表地址: 01317974
虚函数继承FatherFun1地址:01317974
虚函数继承FatherFun2地址:01317978
虚函数继承FatherFun3地址:0131797C
虚函数sonFun1地址:01317980
虚函数sonFun2地址:01317984
虚函数sonFun3地址:01317988
FatherFun1
FatherFun2
FatherFun3
SonFun1
SonFun2
SonFun3
请按任意键继续. . .

由输出结果我们可以看到,父类和子类中的虚函数表地址是不一样的,而且子类继承了父类的虚函数,但是其地址是和父类中不一样的!。第四点确认!
并且我们根据输出可以发现,子类虚函数表中虚函数地址排序为先是继承的父类的函数,再是子类中的虚函数。

在这里插入图片描述

5.子类重写父类中虚函数,或子类重定义父类虚函数

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Father
  6. {
  7. virtual void FatherFun4() {cout << "FatherFun4" <<endl;}
  8. virtual void FatherFun1() {cout << "FatherFun1" <<endl;}
  9. virtual void FatherFun2() {cout << "FatherFun2" <<endl;}
  10. virtual void FatherFun3() {cout << "FatherFun3" <<endl;}
  11. };
  12. class Son : public Father
  13. {
  14. virtual void SonFun1() {cout << "SonFun1" <<endl;}
  15. virtual void SonFun2() {cout << "SonFun2" <<endl;}
  16. virtual void SonFun3() {cout << "SonFun3" <<endl;}
  17. virtual void FatherFun4() {cout << "SonGetFatherFun4" <<endl;}
  18. virtual void FatherFun4(int a = 0) {cout << "SonGetFatherFun4 diffrent param" <<endl;}
  19. };
  20. typedef void (*Fun)(void);
  21. typedef void (*FunParam)(int);
  22. int main()
  23. {
  24. #if 1
  25. Father father;
  26. cout << "类对象地址:" << &father << endl;
  27. cout << "虚函数表地址: " << (int*)*(int*)&father << endl;
  28. cout << "虚函数FatherFun4地址:" <<(int*)*(int*)&father << endl;
  29. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father + 1 << endl;
  30. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father + 2 << endl;
  31. cout << "虚函数FatherFun3地址:" <<(int*)*(int*)&father + 3 << endl;
  32. Fun fun = (Fun)*(int*)*(int*)&father;
  33. fun();
  34. fun = (Fun)*((int*)*(int*)(&father) + 1);
  35. fun();
  36. fun = (Fun)*((int*)*(int*)(&father) + 2);
  37. fun();
  38. fun = (Fun)*((int*)*(int*)(&father) + 3);
  39. fun();
  40. cout << "----------------测试子类------------------" << endl;
  41. Son son;
  42. cout << "类对象地址:" << &son << endl;
  43. cout << "虚函数表地址: " << (int*)*(int*)&son << endl;
  44. cout << "虚函数继承SonGetFatherFun4地址:" <<(int*)*(int*)&son << endl;
  45. cout << "虚函数继承FatherFun1地址:" <<(int*)*(int*)&son + 1 << endl;
  46. cout << "虚函数继承FatherFun2地址:" <<(int*)*(int*)&son + 2 << endl;
  47. cout << "虚函数继承FatherFun3地址:" <<(int*)*(int*)&son + 3 << endl;
  48. cout << "虚函数sonFun1地址:" <<(int*)*(int*)&son + 4 << endl;
  49. cout << "虚函数sonFun2地址:" <<(int*)*(int*)&son + 5 << endl;
  50. cout << "虚函数sonFun3地址:" <<(int*)*(int*)&son + 6 << endl;
  51. cout << "虚函数SonGetFatherFun4 diffrent param地址:" <<(int*)*(int*)&son + 7 << endl;
  52. fun = (Fun)*(int*)*(int*)&son;
  53. fun();
  54. fun = (Fun)*((int*)*(int*)(&son) + 1);
  55. fun();
  56. fun = (Fun)*((int*)*(int*)(&son) + 2);
  57. fun();
  58. fun = (Fun)*((int*)*(int*)(&son) + 3);
  59. fun();
  60. fun = (Fun)*((int*)*(int*)(&son) + 4);
  61. fun();
  62. fun = (Fun)*((int*)*(int*)(&son) + 5);
  63. fun();
  64. fun = (Fun)*((int*)*(int*)(&son) + 6);
  65. fun();
  66. FunParam funParam= (FunParam)*((int*)*(int*)(&son) + 7);
  67. funParam(0);
  68. #endif
  69. system("pause");
  70. }

我们故意将父类中FatherFun4放在最前,而子类中的重写和重定义的FatherFun4 函数放在最后,看一下虚函数表中虚函数排放顺序是否有发生改变。

以下为输出结果:

  1. 类对象地址:0021FD4C
  2. 虚函数表地址: 011479B8
  3. 虚函数FatherFun4地址:011479B8
  4. 虚函数FatherFun1地址:011479BC
  5. 虚函数FatherFun2地址:011479C0
  6. 虚函数FatherFun3地址:011479C4
  7. FatherFun4
  8. FatherFun1
  9. FatherFun2
  10. FatherFun3
  11. ----------------测试子类------------------
  12. 类对象地址:0021FD34
  13. 虚函数表地址: 01147A10
  14. 虚函数继承SonGetFatherFun4地址:01147A10
  15. 虚函数继承FatherFun1地址:01147A14
  16. 虚函数继承FatherFun2地址:01147A18
  17. 虚函数继承FatherFun2地址:01147A1C
  18. 虚函数sonFun1地址:01147A20
  19. 虚函数sonFun2地址:01147A24
  20. 虚函数sonFun3地址:01147A28
  21. 虚函数SonGetFatherFun4 diffrent param地址:01147A2C
  22. **SonGetFatherFun4**
  23. FatherFun1
  24. FatherFun2
  25. FatherFun3
  26. SonFun1
  27. SonFun2
  28. SonFun3
  29. SonGetFatherFun4 diffrent param

我们可以清楚的看到,位于子类最后函数重写的FatherFun4被放在了本该继承的父类FatherFun4位置上(先输出的是SonGetFatherFun4),而函数重定义则没有发生改变。

由此可以得出结论:

(1)覆盖的FatherFun4函数被放到了虚函数表中原父类虚函数的位置

(2)没有被覆盖的函数没有变化

在这里插入图片描述

6.子类指针指向父类

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Father
  6. {
  7. virtual void FatherFun1() {cout << "FatherFun1" <<endl;}
  8. virtual void FatherFun2() {cout << "FatherFun2" <<endl;}
  9. virtual void FatherFun3() {cout << "FatherFun3" <<endl;}
  10. };
  11. class Son : public Father
  12. {
  13. virtual void SonFun1() {cout << "SonFun1" <<endl;}
  14. virtual void SonFun2() {cout << "SonFun2" <<endl;}
  15. virtual void SonFun3() {cout << "SonFun3" <<endl;}
  16. };
  17. #if 0
  18. class Test
  19. {
  20. void TestFun1() {cout << "TestFun1" <<endl;}
  21. void TestFun2() {cout << "TestFun2" <<endl;}
  22. void TestFun3() {cout << "TestFun3" <<endl;}
  23. };
  24. #endif
  25. typedef void (*Fun)(void);
  26. typedef void (*FunParam)(int);
  27. int main()
  28. {
  29. cout << "----------------测试父类------------------" << endl;
  30. Father father;
  31. cout << "类对象地址:" << &father << endl;
  32. cout << "虚函数表地址: " << (int*)*(int*)&father << endl;
  33. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father << endl;
  34. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father + 1 << endl;
  35. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father + 2 << endl;
  36. Fun fun = (Fun)*(int*)*(int*)&father;
  37. fun();
  38. fun = (Fun)*((int*)*(int*)(&father) + 1);
  39. fun();
  40. fun = (Fun)*((int*)*(int*)(&father) + 2);
  41. fun();
  42. cout << "----------------测试子类------------------" << endl;
  43. Son son;
  44. cout << "类对象地址:" << &son << endl;
  45. cout << "虚函数表地址: " << (int*)*(int*)&son << endl;
  46. cout << "虚函数继承FatherFun1地址:" <<(int*)*(int*)&son << endl;
  47. cout << "虚函数继承FatherFun2地址:" <<(int*)*(int*)&son + 1 << endl;
  48. cout << "虚函数继承FatherFun3地址:" <<(int*)*(int*)&son + 2 << endl;
  49. cout << "虚函数sonFun1地址:" <<(int*)*(int*)&son + 3 << endl;
  50. cout << "虚函数sonFun2地址:" <<(int*)*(int*)&son + 4 << endl;
  51. cout << "虚函数sonFun3地址:" <<(int*)*(int*)&son + 5 << endl;
  52. fun = (Fun)*(int*)*(int*)&son;
  53. fun();
  54. fun = (Fun)*((int*)*(int*)(&son) + 1);
  55. fun();
  56. fun = (Fun)*((int*)*(int*)(&son) + 2);
  57. fun();
  58. fun = (Fun)*((int*)*(int*)(&son) + 3);
  59. fun();
  60. fun = (Fun)*((int*)*(int*)(&son) + 4);
  61. fun();
  62. fun = (Fun)*((int*)*(int*)(&son) + 5);
  63. fun();
  64. cout << "----------------测试父类指针指向子类------------------" << endl;
  65. Father* pointSon = new Son;
  66. cout << "类对象地址:" << pointSon << endl;
  67. cout << "虚函数表地址: " << (int*)*(int*)pointSon << endl;
  68. cout << "虚函数继承FatherFun1地址:" <<(int*)*(int*)pointSon << endl;
  69. cout << "虚函数继承FatherFun2地址:" <<(int*)*(int*)pointSon + 1 << endl;
  70. cout << "虚函数继承FatherFun3地址:" <<(int*)*(int*)pointSon + 2 << endl;
  71. cout << "虚函数sonFun1地址:" <<(int*)*(int*)pointSon + 3 << endl;
  72. cout << "虚函数sonFun2地址:" <<(int*)*(int*)pointSon + 4 << endl;
  73. cout << "虚函数sonFun3地址:" <<(int*)*(int*)pointSon + 5 << endl;
  74. fun = (Fun)*(int*)*(int*)pointSon;
  75. fun();
  76. fun = (Fun)*((int*)*(int*)(pointSon) + 1);
  77. fun();
  78. fun = (Fun)*((int*)*(int*)(pointSon) + 2);
  79. fun();
  80. fun = (Fun)*((int*)*(int*)(pointSon) + 3);
  81. fun();
  82. fun = (Fun)*((int*)*(int*)(pointSon) + 4);
  83. fun();
  84. fun = (Fun)*((int*)*(int*)(pointSon) + 5);
  85. fun();
  86. system("pause");
  87. }

实际上父类指针指向子类,调用的是子类的虚函数表。

以下为输出:

----------------测试父类------------------
类对象地址:0029FDD0
虚函数表地址: 000F89BC
虚函数FatherFun1地址:000F89BC
虚函数FatherFun1地址:000F89C0
虚函数FatherFun2地址:000F89C4
FatherFun1
FatherFun2
FatherFun3
----------------测试子类------------------
类对象地址:0029FDB8
虚函数表地址: 000F8A00
虚函数继承FatherFun1地址:000F8A00
虚函数继承FatherFun2地址:000F8A04
虚函数继承FatherFun3地址:000F8A08
虚函数sonFun1地址:000F8A0C
虚函数sonFun2地址:000F8A10
虚函数sonFun3地址:000F8A14
FatherFun1
FatherFun2
FatherFun3
SonFun1
SonFun2
SonFun3
----------------测试父类指针指向子类------------------
类对象地址:003B55D8
虚函数表地址: 000F8A00
虚函数继承FatherFun1地址:000F8A00
虚函数继承FatherFun2地址:000F8A04
虚函数继承FatherFun3地址:000F8A08
虚函数sonFun1地址:000F8A0C
虚函数sonFun2地址:000F8A10
虚函数sonFun3地址:000F8A14
FatherFun1
FatherFun2
FatherFun3
SonFun1
SonFun2
SonFun3
请按任意键继续. . .

由虚函数表地址我们就可以看到,父类指针指向子类的时候,其虚函数表地址和子类虚函数表地址是一样的。由此,第五点确认

7.子类重写父类虚函数,并子类指针指向父类

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. class Father
  6. {
  7. virtual void FatherFun4() {cout << "FatherFun4" <<endl;}
  8. virtual void FatherFun1() {cout << "FatherFun1" <<endl;}
  9. virtual void FatherFun2() {cout << "FatherFun2" <<endl;}
  10. virtual void FatherFun3() {cout << "FatherFun3" <<endl;}
  11. };
  12. class Son : public Father
  13. {
  14. virtual void SonFun1() {cout << "SonFun1" <<endl;}
  15. virtual void SonFun2() {cout << "SonFun2" <<endl;}
  16. virtual void SonFun3() {cout << "SonFun3" <<endl;}
  17. virtual void FatherFun4() {cout << "SonGetFatherFun4" <<endl;}
  18. };
  19. #if 0
  20. class Test
  21. {
  22. void TestFun1() {cout << "TestFun1" <<endl;}
  23. void TestFun2() {cout << "TestFun2" <<endl;}
  24. void TestFun3() {cout << "TestFun3" <<endl;}
  25. };
  26. #endif
  27. typedef void (*Fun)(void);
  28. typedef void (*FunParam)(int);
  29. int main()
  30. {
  31. cout << "----------------测试父类------------------" << endl;
  32. Father father;
  33. cout << "类对象地址:" << &father << endl;
  34. cout << "虚函数表地址: " << (int*)*(int*)&father << endl;
  35. cout << "虚函数FatherFun4地址:" <<(int*)*(int*)&father << endl;
  36. cout << "虚函数FatherFun1地址:" <<(int*)*(int*)&father + 1 << endl;
  37. cout << "虚函数FatherFun2地址:" <<(int*)*(int*)&father + 2 << endl;
  38. cout << "虚函数FatherFun3地址:" <<(int*)*(int*)&father + 3 << endl;
  39. Fun fun = (Fun)*(int*)*(int*)&father;
  40. fun();
  41. fun = (Fun)*((int*)*(int*)(&father) + 1);
  42. fun();
  43. fun = (Fun)*((int*)*(int*)(&father) + 2);
  44. fun();
  45. fun = (Fun)*((int*)*(int*)(&father) + 3);
  46. fun();
  47. cout << "----------------测试子类------------------" << endl;
  48. Son son;
  49. cout << "类对象地址:" << &son << endl;
  50. cout << "虚函数表地址: " << (int*)*(int*)&son << endl;
  51. cout << "虚函数继承FatherFun4地址:" <<(int*)*(int*)&son << endl;
  52. cout << "虚函数继承FatherFun1地址:" <<(int*)*(int*)&son + 1 << endl;
  53. cout << "虚函数继承FatherFun2地址:" <<(int*)*(int*)&son + 2 << endl;
  54. cout << "虚函数继承FatherFun3地址:" <<(int*)*(int*)&son + 3 << endl;
  55. cout << "虚函数sonFun1地址:" <<(int*)*(int*)&son + 4 << endl;
  56. cout << "虚函数sonFun2地址:" <<(int*)*(int*)&son + 5 << endl;
  57. cout << "虚函数sonFun3地址:" <<(int*)*(int*)&son + 6 << endl;
  58. fun = (Fun)*(int*)*(int*)&son;
  59. fun();
  60. fun = (Fun)*((int*)*(int*)(&son) + 1);
  61. fun();
  62. fun = (Fun)*((int*)*(int*)(&son) + 2);
  63. fun();
  64. fun = (Fun)*((int*)*(int*)(&son) + 3);
  65. fun();
  66. fun = (Fun)*((int*)*(int*)(&son) + 4);
  67. fun();
  68. fun = (Fun)*((int*)*(int*)(&son) + 5);
  69. fun();
  70. fun = (Fun)*((int*)*(int*)(&son) + 6);
  71. fun();
  72. cout << "----------------测试父类指针指向子类------------------" << endl;
  73. Father* pointSon = new Son;
  74. cout << "类对象地址:" << pointSon << endl;
  75. cout << "虚函数表地址: " << (int*)*(int*)pointSon << endl;
  76. cout << "虚函数继承FatherFun1地址:" <<(int*)*(int*)pointSon << endl;
  77. cout << "虚函数继承FatherFun2地址:" <<(int*)*(int*)pointSon + 1 << endl;
  78. cout << "虚函数继承FatherFun3地址:" <<(int*)*(int*)pointSon + 2 << endl;
  79. cout << "虚函数sonFun1地址:" <<(int*)*(int*)pointSon + 3 << endl;
  80. cout << "虚函数sonFun2地址:" <<(int*)*(int*)pointSon + 4 << endl;
  81. cout << "虚函数sonFun3地址:" <<(int*)*(int*)pointSon + 5 << endl;
  82. fun = (Fun)*(int*)*(int*)pointSon;
  83. fun();
  84. fun = (Fun)*((int*)*(int*)(pointSon) + 1);
  85. fun();
  86. fun = (Fun)*((int*)*(int*)(pointSon) + 2);
  87. fun();
  88. fun = (Fun)*((int*)*(int*)(pointSon) + 3);
  89. fun();
  90. fun = (Fun)*((int*)*(int*)(pointSon) + 4);
  91. fun();
  92. fun = (Fun)*((int*)*(int*)(pointSon) + 5);
  93. fun();
  94. fun = (Fun)*((int*)*(int*)(pointSon) + 6);
  95. fun();
  96. system("pause");
  97. }

直接看输出结果:

  1. ----------------测试父类------------------
  2. 类对象地址:0034F788
  3. 虚函数表地址: 000B8A14
  4. 虚函数FatherFun4地址:000B8A14
  5. 虚函数FatherFun1地址:000B8A18
  6. 虚函数FatherFun2地址:000B8A1C
  7. 虚函数FatherFun3地址:000B8A20
  8. FatherFun4
  9. FatherFun1
  10. FatherFun2
  11. FatherFun3
  12. ----------------测试子类------------------
  13. 类对象地址:0034F770
  14. 虚函数表地址: 000B8A6C
  15. 虚函数继承FatherFun4地址:000B8A6C
  16. 虚函数继承FatherFun1地址:000B8A70
  17. 虚函数继承FatherFun2地址:000B8A74
  18. 虚函数继承FatherFun3地址:000B8A78
  19. 虚函数sonFun1地址:000B8A7C
  20. 虚函数sonFun2地址:000B8A80
  21. 虚函数sonFun3地址:000B8A84
  22. SonGetFatherFun4
  23. FatherFun1
  24. FatherFun2
  25. FatherFun3
  26. SonFun1
  27. SonFun2
  28. SonFun3
  29. ----------------测试父类指针指向子类------------------
  30. 类对象地址:005855D8
  31. 虚函数表地址: 000B8A6C
  32. 虚函数继承FatherFun1地址:000B8A6C
  33. 虚函数继承FatherFun2地址:000B8A70
  34. 虚函数继承FatherFun3地址:000B8A74
  35. 虚函数sonFun1地址:000B8A78
  36. 虚函数sonFun2地址:000B8A7C
  37. 虚函数sonFun3地址:000B8A80
  38. SonGetFatherFun4
  39. FatherFun1
  40. FatherFun2
  41. FatherFun3
  42. SonFun1
  43. SonFun2
  44. SonFun3
  45. 请按任意键继续. . .

实际上和第六点结果是一样的

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/244010
推荐阅读
相关标签
  

闽ICP备14008679号