C++ InputReactor事件接收类冗余事件虚函数优化方案咨询
优化方案1:CRTP静态分发+统一虚函数入口
该方案只保留基类的单个虚函数作为事件入口,所有事件的路由逻辑仅编写一次,完全消除十多个重复虚函数声明的冗余,同时保留原有的子类按需重写事件处理函数的使用习惯。
// 先补充EVENTS枚举的定义示例 enum class EVENTS { QUIT, LEFT, RIGHT, UP, DOWN, AXISUPD, OK, CANCEL, SHIFT, CTRL, MAX_EVENTS }; // 基础基类 class InputReactor { public: InputReactor(Input* input_) : m_input(input_) {} // 仅保留1个虚函数作为事件总入口 virtual void on_input(EVENTS ev, float scale_) = 0; std::vector<EVENTS> subscribed_at; void setInputEnabled(bool inputEnabled_) { m_inputEnabled = inputEnabled_; } bool isInputEnabled() { return m_inputEnabled; } virtual ~InputReactor() { for (EVENTS ev : subscribed_at) { m_input->unsubscribe(ev, this); } } protected: Input* m_input = nullptr; bool m_inputEnabled = false; }; // CRTP中间层,统一实现事件路由逻辑,所有子类复用 template<typename Derived> class InputReactorCRTP : public InputReactor { public: using InputReactor::InputReactor; void on_input(EVENTS ev, float scale_) override { // 统一处理输入启停控制,符合需求 if (!isInputEnabled()) return; switch(ev) { case EVENTS::QUIT: static_cast<Derived*>(this)->input_quit(scale_); break; case EVENTS::LEFT: static_cast<Derived*>(this)->input_left(scale_); break; case EVENTS::RIGHT: static_cast<Derived*>(this)->input_right(scale_); break; case EVENTS::UP: static_cast<Derived*>(this)->input_up(scale_); break; case EVENTS::DOWN: static_cast<Derived*>(this)->input_down(scale_); break; case EVENTS::AXISUPD: static_cast<Derived*>(this)->input_axisupd(scale_); break; case EVENTS::OK: static_cast<Derived*>(this)->input_ok(scale_); break; case EVENTS::CANCEL: static_cast<Derived*>(this)->input_cancel(scale_); break; case EVENTS::SHIFT: static_cast<Derived*>(this)->input_shift(scale_); break; case EVENTS::CTRL: static_cast<Derived*>(this)->input_ctrl(scale_); break; default: break; } } // 提供所有事件的默认空实现,子类不需要处理的事件无需重写 void input_quit(float scale_) {} void input_left(float scale_) {} void input_right(float scale_) {} void input_up(float scale_) {} void input_down(float scale_) {} void input_axisupd(float scale_) {} void input_ok(float scale_) {} void input_cancel(float scale_) {} void input_shift(float scale_) {} void input_ctrl(float scale_) {} };
子类使用方式和原有逻辑几乎完全兼容,仅需修改继承方式:
class MyReactor : public InputReactorCRTP<MyReactor> { public: using InputReactorCRTP::InputReactorCRTP; // 仅需要重写自身需要处理的事件即可 void input_quit(float scale_) { // 自定义退出逻辑 } void input_ok(float scale_) { // 自定义确认逻辑 } };
优化方案2:回调注册机制,完全消除虚函数
如果不需要继承重写的模式,可以直接用回调表实现,代码冗余更低,运行开销更小:
class InputReactor { public: InputReactor(Input* input_) : m_input(input_) {} // 事件注册接口 template<EVENTS ev, typename Func> void register_callback(Func&& func) { m_callbacks[static_cast<size_t>(ev)] = std::forward<Func>(func); subscribed_at.push_back(ev); } // Input类调用的事件触发入口 void trigger(EVENTS ev, float scale_) { if (!m_inputEnabled) return; auto& cb = m_callbacks[static_cast<size_t>(ev)]; if (cb) cb(scale_); } std::vector<EVENTS> subscribed_at; void setInputEnabled(bool inputEnabled_) { m_inputEnabled = inputEnabled_; } bool isInputEnabled() { return m_inputEnabled; } virtual ~InputReactor() { for (EVENTS ev : subscribed_at) { m_input->unsubscribe(ev, this); } } private: Input* m_input = nullptr; bool m_inputEnabled = false; std::array<std::function<void(float)>, static_cast<size_t>(EVENTS::MAX_EVENTS)> m_callbacks; };
子类使用示例:
class MyReactor : public InputReactor { public: MyReactor(Input* input) : InputReactor(input) { // 需要处理什么事件就注册什么,无需冗余声明 register_callback<EVENTS::QUIT>([this](float scale) { // 退出逻辑 }); register_callback<EVENTS::OK>([this](float scale) { // 确认逻辑 }); } };
内容的提问来源于stack exchange,提问作者SavedowW
相关产品推荐
相关产品推荐

