whz_time 2024-04-16 20:04 采纳率: 100%
浏览 2
已结题

关于C++ 虚函数问题讨论:有谁能解释这一奇怪的现象:

关于C++ 虚函数问题讨论:有谁能解释这一奇怪的现象:
先直接贴上代码如下:

// =================================================================================
// Online C++ compiler to run C++ program online
#include <iostream>
class cta
{
public:
    virtual int test(int n)
    {
        return n*3;
    }
};
class ctb : public cta
{
public:
    virtual int test(int n)
    {
        // return cta::test(n);
        return n;
    }
};
typedef int (cta::*CTMemProc)(int);
int main() 
{
    cta a;
    ctb b;
    CTMemProc mpfA = &cta::test;
    CTMemProc mpfB = (CTMemProc)(&ctb::test);
    if(mpfA == mpfB)
    {
        std::cout << "mfpA == mfpB" << std::endl;
    }
    else
    {
        std::cout << "mfpA != mfpB" << std::endl;
    }
    std::cout << "a.test()=" << (a.*mpfA)(2) << std::endl;
    std::cout << "a.test()=" << (b.*mpfB)(2) << std::endl;
    return 0;
}
// =================================================================================

执行的结果输出如下:
mfpA == mfpB
a.test()=6
a.test()=2

问题, 既然 mfpA 和 mfpB 是相同的,为什么执行了两个不同的函数结果呢, 仅仅只是因为他们的 object 是不同的吗, 但是这个程序跟object无关呀, 只跟函数的入口地址相关呀。
请各位专家帮忙解释一下。
谢谢.

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-16 20:04
    关注

    引自免费微信小程序:皆我百晓生

    在C++中,虚函数是面向对象编程中的一个重要特性,它允许子类重写基类的方法。当通过基类指针或引用调用虚函数时,实际执行的是根据运行时的对象类型调用相应的子类方法。然而,当你将虚函数的成员指针(如CTMemProc)赋值给不同类型的对象并调用它们时,情况会有所不同。

    首先,让我们澄清一点:mfpAmfpB确实是相同的,因为它们都指向各自的test函数的地址。但是,当你使用成员指针调用函数时,实际上是隐式地与某个对象关联起来。这与直接通过对象调用虚函数的行为不同,因为在这种情况下,编译器知道要调用哪个版本的虚函数。

    在你的代码中,尽管mfpAmfpB指向同一段内存(即test函数的地址),但当你用它们分别对ab进行操作时,行为会因对象类型的不同而改变。这是因为成员指针调用隐含了一个对象作为参数传递,即this指针。

    下面是详细的解释:

    1. 当你使用(a.*mpfA)(2)时,虽然mpfA指向cta::test的地址,但由于你是在cta对象a上调用的,因此实际执行的是cta::test,返回n * 3,所以输出为a.test()=6

    2. 然后,当你使用(b.*mpfB)(2)时,虽然mpfB也指向cta::test的地址,但在ctb对象b上调用时,由于ctb覆盖了ctatest函数,因此实际执行的是ctb::test,返回n,所以输出为a.test()=2

    总结来说,即使成员指针指向同一个虚函数地址,其实际执行的函数取决于调用它的对象的实际类型。当你使用成员指针调用虚函数时,编译器并不考虑虚函数表(vtable)和动态绑定,而是简单地将指针所指向的函数应用到指定的对象上,就像非虚函数那样。如果你想要通过成员指针实现动态绑定的效果,你需要使用虚成员指针(即指向虚函数的指针),但这通常不推荐这样做,因为它可能导致难以理解和维护的代码。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 4月25日
  • 已采纳回答 4月17日
  • 创建了问题 4月16日

悬赏问题

  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序
  • ¥15 多址通信方式的抗噪声性能和系统容量对比