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

基类重载*运算符实现派生类复用及ProductFilter调用派生类方法问题

解决ISignalFilter派生类组合时的多态调用问题

你的问题核心是对象切片:当派生类对象被赋值给基类对象时,派生类的特有数据和虚函数表会被截断,导致ProductFilter中存储的a_和b_实际是基类实例,调用filtered_value时只会执行基类版本。要解决这个问题,必须通过指针或引用实现多态,这里推荐使用智能指针来自动管理内存。

修正后的完整代码

#include <iostream>
#include <memory>
using namespace std;

template <typename T>
class ISignalFilter;

template <typename F>
class ProductFilter;

template <typename T>
class ISignalFilter : public std::enable_shared_from_this<ISignalFilter<T>> {
public:
    // 虚析构函数:确保派生类析构函数被正确调用
    virtual ~ISignalFilter() = default;
    // 纯虚函数:强制派生类必须实现过滤逻辑
    virtual T filtered_value(const T& value) = 0;
    // 重载*运算符:返回组合后的ProductFilter,使用智能指针传递对象
    ProductFilter<T> operator*(std::shared_ptr<ISignalFilter<T>> other) {
        return ProductFilter<T>(this->shared_from_this(), std::move(other));
    }
};

template <typename F>
class ProductFilter : public ISignalFilter<F> {
public:
    // 构造函数:接收智能指针,避免对象切片
    ProductFilter(std::shared_ptr<ISignalFilter<F>> a, std::shared_ptr<ISignalFilter<F>> b)
        : a_(std::move(a)), b_(std::move(b)) {}

    // 实现过滤逻辑:通过智能指针调用派生类的filtered_value
    F filtered_value(const F& value) override {
        return b_->filtered_value(a_->filtered_value(value));
    }

private:
    // 用智能指针存储基类对象,保持多态性
    std::shared_ptr<ISignalFilter<F>> a_;
    std::shared_ptr<ISignalFilter<F>> b_;
};

template <typename T>
class IdentityFilter : public ISignalFilter<T> {
public:
    T filtered_value(const T& value) override {
        return value;
    }
};

int main() {
    // 使用shared_ptr创建派生类对象
    auto filter1 = std::make_shared<IdentityFilter<int>>();
    // 组合两个过滤器
    auto filter2 = *filter1 * filter1;
    // 输出1,正确调用IdentityFilter的filtered_value
    std::cout << filter2.filtered_value(1) << std::endl;
    return 0;
}

关键修改说明

  • 虚析构函数:基类必须声明虚析构函数,否则通过基类指针销毁派生类对象时会触发未定义行为。
  • 智能指针存储:用std::shared_ptr<ISignalFilter<F>>替代直接存储基类对象,避免对象切片,同时自动管理内存。
  • enable_shared_from_this:让基类继承该模板类,允许在成员函数operator*中获取当前对象的shared_ptr,确保组合时传递的是正确的对象引用。
  • 纯虚函数:将filtered_value改为纯虚函数,强制所有派生类必须实现自己的过滤逻辑,避免意外调用基类的错误分支。

替代方案(使用原始指针)

如果不想用智能指针,也可以使用原始指针,但需要手动管理内存,注意避免内存泄漏:

// 修改ProductFilter的成员和构造函数
template <typename F>
class ProductFilter : public ISignalFilter<F> {
public:
    ProductFilter(ISignalFilter<F>* a, ISignalFilter<F>* b) : a_(a), b_(b) {}
    ~ProductFilter() override {
        // 注意:如果外部已经释放了指针,这里会重复释放,需要明确内存所有权
        delete a_;
        delete b_;
    }
    F filtered_value(const F& value) override {
        return b_->filtered_value(a_->filtered_value(value));
    }
private:
    ISignalFilter<F>* a_;
    ISignalFilter<F>* b_;
};

这种方式需要严格控制对象的生命周期,容易出错,因此更推荐智能指针方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:35:35