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

为何调用基类operator()而非派生类?如何调用派生类operator()?

为什么我的表达式类调用的是基类的operator()而非派生类?

嘿,这个问题的核心原因是对象切片(Object Slicing)——C++里新手很容易踩的一个经典坑!

问题根源

你看你定义的e_add结构体里,_left和_right是expr类型的直接对象,而不是指针或者引用。当你把const_value对象传给e_add的构造函数时,编译器会只拷贝const_value里属于基类expr的部分,派生类特有的成员(比如const_value的_value)会被直接"切掉"。这时候调用_left(arg),本质上是在调用基类expr的operator(),完全触发不了派生类的虚函数覆盖逻辑。

简单来说:C++的虚函数多态必须通过指针或引用来实现,直接存储基类对象会丢失派生类的类型信息,导致多态失效。

解决方法:用指针/智能指针保存基类引用

我们可以把e_add里的成员改成智能指针(推荐,更安全,自动管理内存),或者原始指针。下面是用std::unique_ptr修正后的完整代码:

#include <iostream>
#include <cmath>
#include <memory> // 引入智能指针头文件
using namespace std;

struct expr {
    virtual double operator()(double) { 
        cerr << "EXPR::operator() called\n"; 
        return 100500; 
    };
    // 基类必须加虚析构函数,确保派生类析构函数能被正确调用
    virtual ~expr() = default;
};

struct const_value : public expr {
    double _value;
    const_value(double value = 0): _value(value) {};
    double operator()(double arg = 0) override { 
        cout << "const_value " << _value << " called arg = " << arg << '\n'; 
        return _value; 
    };
};

#define make_bin_op(_op_name, _op) \
struct e_##_op_name : public expr { \
    unique_ptr<expr> _left; \
    unique_ptr<expr> _right; \
    // 用move转移智能指针所有权,避免拷贝
    e_##_op_name(unique_ptr<expr> left, unique_ptr<expr> right): _left(move(left)), _right(move(right)) {}; \
    double operator()(double arg) override { \
        return (*_left)(arg) _op (*_right)(arg); \
    }; \
}

make_bin_op(add, +);
#undef make_bin_op

int main() {
    auto c1 = make_unique<const_value>(1);
    e_add e{move(c1), make_unique<const_value>(1)};
    cout << e(100) << endl;
    
    auto c2 = make_unique<const_value>(1);
    cout << (*c2)(100) << endl;
    return 0;
}

关键修正点

  1. 将e_add的_left/_right改为unique_ptr<expr>,通过智能指针保留派生类的类型信息,实现多态调用。
  2. 基类添加了虚析构函数,防止内存泄漏(如果用原始指针的话,也需要手动管理析构)。
  3. 用make_unique创建智能指针,构造e_add时用move转移所有权,避免不必要的拷贝。

如果不想用智能指针,也可以用原始指针,但要注意手动管理内存(比如在析构函数里释放指针),不过智能指针的安全性更高,更推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:36:46