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

C++函数式事件驱动框架:注册模板函数指针为默认事件动作

看起来你已经把核心的事件分发逻辑跑通了,给未注册事件加通用默认动作这个需求非常合理——既能避免未处理事件导致的异常,又能统一兜底逻辑。下面我给你一套具体的实现方案,完全贴合你说的函数式风格和模板化通用默认动作的需求:

实现C++函数式事件驱动框架的通用默认动作

1. 定义通用默认动作模板

先写一个通用的模板函数作为默认动作的基础实现,它可以适配任意事件类型,你可以根据需求修改兜底逻辑(比如打印日志、记录监控、抛出警告等):

#include <iostream>
#include <typeinfo>

template<typename EventType>
void defaultEventAction(const EventType& event) {
    // 通用默认逻辑:输出事件类型信息,可按需扩展
    std::cout << "[Default Action] Handling unregistered event type: " 
              << typeid(EventType).name() << std::endl;
}

2. 改造驱动类,添加默认动作注册机制

你的驱动类需要维护两套映射:一套是已注册的事件-动作,另一套是事件类型对应的默认动作。通过模板方法完成注册,并在分发时优先使用自定义动作,没有则 fallback 到默认动作:

#include <unordered_map>
#include <typeindex>
#include <functional>
#include <stdexcept>

class EventDriver {
private:
    // 存储自定义事件动作:用type_index作为事件类型的唯一标识
    std::unordered_map<std::type_index, std::function<void(const void*)>> customActions_;
    // 存储默认事件动作
    std::unordered_map<std::type_index, std::function<void(const void*)>> defaultActions_;

    // 辅助工具:将强类型函数转换为类型擦除的通用函数
    template<typename EventType>
    std::function<void(const void*)> wrapAction(std::function<void(const EventType&)> action) {
        return [action](const void* eventPtr) {
            action(*static_cast<const EventType*>(eventPtr));
        };
    }

public:
    // 原有:注册自定义事件动作
    template<typename EventType>
    void registerAction(std::function<void(const EventType&)> action) {
        customActions_[std::type_index(typeid(EventType))] = wrapAction(action);
    }

    // 新增:注册指定事件类型的默认动作,默认使用通用模板
    template<typename EventType>
    void registerDefaultAction(std::function<void(const EventType&)> action = defaultEventAction<EventType>) {
        defaultActions_[std::type_index(typeid(EventType))] = wrapAction(action);
    }

    // 事件分发核心逻辑
    template<typename EventType>
    void dispatchEvent(const EventType& event) {
        const auto typeIdx = std::type_index(typeid(EventType));
        
        // 优先使用自定义动作
        auto customIt = customActions_.find(typeIdx);
        if (customIt != customActions_.end()) {
            customIt->second(&event);
            return;
        }

        // 没有自定义动作则尝试默认动作
        auto defaultIt = defaultActions_.find(typeIdx);
        if (defaultIt != defaultActions_.end()) {
            defaultIt->second(&event);
            return;
        }

        // 若连默认动作都没注册,可选择抛出异常或静默忽略
        throw std::runtime_error("No action or default action registered for this event type");
    }
};

3. 使用示例

下面是一个简单的使用场景,展示自定义动作、默认动作的注册和事件分发:

// 定义示例事件类
class MouseClickEvent {
public:
    int x, y;
    MouseClickEvent(int x_, int y_) : x(x_), y(y_) {}
};

class KeyPressEvent {
public:
    char key;
    KeyPressEvent(char k) : key(k) {}
};

int main() {
    EventDriver driver;

    // 给鼠标点击事件注册自定义动作
    driver.registerAction<MouseClickEvent>([](const MouseClickEvent& e) {
        std::cout << "[Custom Action] Mouse clicked at (" << e.x << ", " << e.y << ")\n";
    });

    // 给键盘按下事件注册通用默认动作
    driver.registerDefaultAction<KeyPressEvent>();

    // 分发已注册自定义动作的事件
    driver.dispatchEvent(MouseClickEvent(150, 250));
    // 分发只有默认动作的事件
    driver.dispatchEvent(KeyPressEvent('S'));

    return 0;
}

4. 可选扩展:全局默认动作

如果希望所有未注册的事件都使用同一个兜底逻辑,而不是按类型单独注册,可以给驱动类添加全局默认动作的支持:

// 在EventDriver类中新增成员和方法
private:
    std::function<void(const std::type_index&, const void*)> globalDefaultAction_;

public:
    void setGlobalDefaultAction(std::function<void(const std::type_index&, const void*)> action) {
        globalDefaultAction_ = std::move(action);
    }

// 修改dispatchEvent中的兜底逻辑:
else {
    if (globalDefaultAction_) {
        globalDefaultAction_(typeIdx, &event);
    } else {
        throw std::runtime_error("No action, default action, or global default action registered");
    }
}

对应的全局默认动作可以这样设置:

driver.setGlobalDefaultAction([](const std::type_index& type, const void*) {
    std::cout << "[Global Default] Handling unregistered event: " << type.name() << std::endl;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:57:49