鱼C论坛

 找回密码
 立即注册
查看: 2810|回复: 6

C++类中只有通过指针调用函数的时候才能形成覆盖的效果吗

[复制链接]
发表于 2016-8-18 17:40:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 wenmingxing 于 2016-8-18 17:42 编辑

C++ 类中只有通过指针调用函数才能形成   覆盖   吗
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-8-18 18:42:28 | 显示全部楼层
不大明白你的意思, 可以说清楚些吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-8-18 19:31:23 | 显示全部楼层
浅云纸月 发表于 2016-8-18 18:42
不大明白你的意思, 可以说清楚些吗

就是只有通过指针的形式调用函数才能形成覆盖基类函数的效果吗,如果不通过指针调用那直接通过a.fun这种形式不就相当于基类函数没有被覆盖吗
  1. #include<iostream>

  2. using namespace std;

  3. class A
  4. {
  5. public :
  6.     virtual void play();
  7. };

  8. class B : public A
  9. {
  10. public :
  11.     void play();
  12. };

  13. void A :: play()
  14. {
  15.     cout << "AAA" << endl;
  16. }

  17. void B :: play()
  18. {
  19.     cout << "BBB" << endl;
  20. }

  21. main()
  22. {
  23.     A a;
  24.     B b;

  25.     a.play();           //不覆盖

  26.     A *aa;
  27.     aa=&b;

  28.     aa -> play();             //覆盖
  29. }
复制代码


上面例子main中的a.play就是没有覆盖效果输出AAA,a->play覆盖输出BBB
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-18 20:59:24 | 显示全部楼层
本帖最后由 浅云纸月 于 2016-8-19 22:46 编辑

直接在外部调用基类A的函数也可以实现 ...  不过确实可以实现, 会麻烦一点.  我写了下代码, 你看一下, 不懂的尽管问


  1. #include "stdafx.h"
  2. #include <iostream>

  3. #include <windows.h>


  4. using namespace std;

  5. class A
  6. {
  7. public:
  8.         virtual void play();
  9. };

  10. class B : public A
  11. {
  12. public:
  13.         void play();
  14. };

  15. void A::play()
  16. {
  17.        
  18.         cout << "AAA" << endl;
  19. }

  20. void B::play()
  21. {
  22.         cout << "BBB" << endl;
  23. }

  24. int main()
  25. {
  26.         // 获取类 A 的 vftable
  27.         struct tagCLASS
  28.         {
  29.                 DWORD *pVMT;
  30.         };
  31.         A a;
  32.         DWORD *pVMT = ((tagCLASS *)(&a))->pVMT;

  33.         // 获取 vftable 中的 play() 函数的内存地址
  34.         static void(__fastcall *pfnA_Play)(void *pthis) = NULL;
  35.         pfnA_Play = (void(__fastcall *)(void *pthis))pVMT[0];

  36.         B b;
  37.         A* aa = &b;

  38.         // 调用 类A 的play()函数
  39.         pfnA_Play(aa);

  40.     return 0;
  41. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-19 22:26:34 | 显示全部楼层
其实应该是指针和引用都可以的,在使用虚函数的前提下可以实现动态编联,能够正确的调用对象的函数
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-19 23:10:51 | 显示全部楼层
这就要从汇编层面上看了:每一个对象头部4Bytes指向虚函数表,对象A和对象B都有一个虚函数表,如果用指针P的话,P指向A就用A的虚函数表,P指向B就用B的虚函数表,这么简单的一个东西就实现了所谓多态性。不用指针的话,用的虚函数表都是不变的,所以每一个对象用到的函数都不会变。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-21 23:20:10 | 显示全部楼层
基函数中函数声明为虚函数,在用指针调用的过程中实现动态绑定。这是面向对象语言的多态性。另外,你的代码有问题。
  1. #include<iostream>

  2. using namespace std;

  3. class A
  4. {
  5. public :
  6.     virtual void play();
  7. };

  8. class B : public A
  9. {
  10. public :
  11.     void play();
  12. };

  13. void  A :: play()
  14. {
  15.     cout << "AAA" << endl;
  16. }

  17. void B :: play()
  18. {
  19.     cout << "BBB" << endl;
  20. }

  21. int main()
  22. {
  23.     A a;
  24.     B b;

  25.     a.play();           //调用基类的函数,输出AAA
  26.         b.play();                        //调用继承类的函数,输出BBB
  27.     A *aa;
  28.     aa=&b;                                       

  29.     aa -> play();        //实现类的动态绑定,输出BBB
  30.        
  31. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-13 20:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表