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

Subject/Observer模式下,基于纯虚基类的子类如何优雅生成多事件类型的Override Update方法

Subject/Observer模式下,基于纯虚基类的子类如何优雅生成多事件类型的Override Update方法

嗨,这个场景我太有共鸣了!当观察者类要同时监听N种事件,每个都得手动写一遍Update的override,不仅重复代码多,还容易漏写或者写错类型,用宏虽然能解决,但总觉得不够“优雅”。给你分享几个纯C++原生的优雅方案,完全不用依赖宏:

方案一:CRTP转发基类(兼容C++11及以上)

这是最常用也最兼容的方案,核心是用一个模板转发类,把observer<T>要求的Update调用,转发给我们自己的通用处理方法。

首先定义这个转发基类:

template <typename EventType, typename Derived>
class ObserverForwarder : public observer<EventType> {
public:
    void Update(const EventType& event) override {
        // 安全地转发给子类的通用处理方法
        static_cast<Derived*>(this)->UpdateInternal(event);
    }
};

然后我们的Manager类只需要继承对应事件类型的转发基类,再实现一次通用的UpdateInternal模板方法就行:

class Manager : public ObserverForwarder<eventA, Manager>, 
                public ObserverForwarder<eventB, Manager> {
public:
    // 通用的模板处理逻辑,只需要写一次
    template <typename T>
    void UpdateInternal(const T& event) {
        // 这里写所有事件的通用处理逻辑,比如:
        std::cout << "处理事件: " << typeid(T).name() << std::endl;
        // 后续如果要加新事件,只需要在继承列表里加ObserverForwarder<NewEvent, Manager>就行
    }
};

这个方案的好处:

  • 完全没有宏的预编译期问题,代码可读性拉满
  • 类型安全,编译器会帮你检查所有继承的observer<T>是否都有正确的Update实现
  • 新增事件只需要修改继承列表,不用改其他逻辑,扩展性极强

方案二:C++17+ 用if constexpr 实现差异化处理

如果你的项目已经升级到C++17或以上,还能在通用的UpdateInternal里直接用if constexpr,给特定事件类型加专属逻辑,不用写额外的特化:

template <typename T>
void UpdateInternal(const T& event) {
    // 通用逻辑
    std::cout << "通用处理事件: " << typeid(T).name() << std::endl;

    // 针对eventA的专属逻辑,编译期就会确定分支
    if constexpr (std::is_same_v<T, eventA>) {
        std::cout << "这是eventA的特殊处理" << std::endl;
        // 这里可以直接调用eventA的专属方法
    }
    // 其他事件的专属逻辑同理
}

这种方式把所有逻辑都集中在一个方法里,不用分散到不同的特化函数里,代码更紧凑。

方案三:模板特化实现完全差异化的处理

如果某些事件的逻辑和通用逻辑差异极大,完全不想写在同一个方法里,还可以给UpdateInternal做模板特化:

// 通用模板(默认逻辑)
template <typename T>
void UpdateInternal(const T& event) {
    std::cout << "通用处理事件: " << typeid(T).name() << std::endl;
}

// 针对eventA的特化实现
template <>
void UpdateInternal<eventA>(const eventA& event) {
    std::cout << "eventA专属处理逻辑" << std::endl;
    // 这里写eventA的完整专属代码
}

这种方式既保留了通用逻辑的复用,又能给特殊事件完全独立的实现,灵活性拉满。

以上这些方案都比宏的方式更优雅,完全符合C++的类型安全特性,也更容易维护和扩展。

备注:内容来源于stack exchange,提问作者alexbuisson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 12:04:30