You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++多态问题:调用错误对象的成员函数求助

问题根源与解决方案

核心问题:违反单一定义规则(ODR)

你遇到的多态调用异常本质是C++单一定义规则(One Definition Rule)被违反:

  • 在derived_1.cpp和derived_2.cpp中,你分别定义了完全同名的derivedCallBack_t类,且未通过命名空间等方式隔离。
  • C++要求同一程序中每个类的定义必须唯一,链接阶段编译器会将这两个同名类视为同一实体,导致它们的虚函数表被错误合并。最终调用virtualFunction时,实际执行的是链接器优先选取的版本(比如derived_1.cpp中的实现,导致globalFlag被设为1)。

此外,构造函数写法存在冗余,还可能引发潜在的引用生命周期风险:

  • _base(base_t(*_derivedCallBack))会先创建临时base_t对象,再通过拷贝构造初始化_base。虽然此处*_derivedCallBack是堆对象,引用不会立即悬垂,但这种写法完全没必要,且易引发误解。

修复方案

1. 隔离同名类(解决ODR问题)

给两个cpp文件中的回调类添加独立命名空间,或直接修改类名避免冲突:

方式一:使用命名空间

修改derived_1.cpp:

#include "base.hpp"

namespace derived1 {
class derivedCallBack_t : public base_t::callBack_t
{
public:
    void virtualFunction(void) {
        globalFlag = 1;
    }
};
} // namespace derived1

class derived_1_t
{
public:
    derived_1_t(void);
    
    derived1::derivedCallBack_t* _derivedCallBack;
    base_t _base;
};

derived_1_t::derived_1_t(void):
    _derivedCallBack(new derived1::derivedCallBack_t()),
    _base(*_derivedCallBack) // 去掉临时对象,直接初始化
{}

修改derived_2.cpp:

#include <iostream>
#include "base.hpp"

namespace derived2 {
class derivedCallBack_t : public base_t::callBack_t
{
public:
    void virtualFunction(void) {
        globalFlag = 2;
    }
};
} // namespace derived2

class derived_2_t
{
public:
    derived_2_t(void):
        _derivedCallBack(new derived2::derivedCallBack_t()),
        _base(*_derivedCallBack) // 去掉临时对象,直接初始化
    {}

    derived2::derivedCallBack_t* _derivedCallBack;
    base_t _base;
};


int globalFlag = 0;
int main()
{
    derived_2_t derived = derived_2_t();
    derived._base.run();
    std::cout << "globalFlag " << globalFlag; // 此时会输出2
}

方式二:修改类名

直接将derived_1.cpp中的回调类改为derived1CallBack_t,derived_2.cpp中的改为derived2CallBack_t,从根源避免同名冲突。

2. 修复构造函数初始化方式

将_base(base_t(*_derivedCallBack))简化为_base(*_derivedCallBack),直接用堆对象的引用初始化_base,避免不必要的临时对象创建。

验证结果

修复后运行程序,globalFlag会被正确设为2,符合预期。

内容的提问来源于stack exchange,提问作者Hagai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:55:38