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

C++中能否通过模板实现适配不同监听器接口的通用事件收集器?

解决方案

完全可以实现通用的收集器逻辑,核心思路是通过模板封装通用的事件存储、访问逻辑,配合少量宏适配不同监听器的虚函数名,彻底消除重复代码。


1. 通用基类模板实现

首先封装所有收集器共用的事件存储、查询逻辑,这部分和具体监听器、虚函数名无关:

#include <vector>

template <typename EventT>
class EventCollectorBase
{
public:
    const std::vector<EventT>& events() const
    {
        return m_events;
    }
protected:
    std::vector<EventT> m_events;
};

2. 宏定义自动生成收集器类

由于不同监听器的虚函数名是编译期标识符,无法通过模板直接操作,我们用一个极简的宏来自动生成对应收集器的重写逻辑:

#define DEFINE_EVENT_COLLECTOR(CollectorName, ListenerT, EventT, CallbackFuncName) \
class CollectorName : public ListenerT, public EventCollectorBase<EventT> \
{ \
private: \
    void CallbackFuncName(const EventT& event) override { \
        m_events.emplace_back(event); \
    } \
}

3. 使用方式

新增对应监听器的收集器仅需一行代码,完全不需要重复编写类结构:

// 生成ListenerA对应的事件收集器
DEFINE_EVENT_COLLECTOR(EventACollector, ListenerA, EventA, onEventA);
// 生成ListenerB对应的事件收集器
DEFINE_EVENT_COLLECTOR(EventBCollector, ListenerB, EventB, onEventB);

使用逻辑和你之前手写的收集器完全一致:

// 测试使用示例
EventACollector a_collector;
// 注册到事件触发模块
test_module.register_listener(&a_collector);
// 触发事件后读取收集结果
for (const auto& event : a_collector.events()) {
    // 执行测试断言、分析逻辑
    ASSERT_EQ(event.id, expected_id);
}

补充说明

如果不想使用宏,也可以通过模板特化的方式实现,只是每次需要手动写重写方法的逻辑:

// 通用收集器模板
template <typename ListenerT, typename EventT>
class EventCollector : public ListenerT, public EventCollectorBase<EventT> {};

// 特化实现ListenerA的回调
template <>
void EventCollector<ListenerA, EventA>::onEventA(const EventA& event) override {
    m_events.emplace_back(event);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:06:01