c++ - 事件系统 : Inheritance with type-casting or unions

标签 c++ events event-handling game-engine unions

我目前正在为我的游戏引擎开发一个事件系统。我想过两种方法可以实现它:

1. 带继承:

class Event
{
    //...
    Type type; // Event type stored using an enum class
}

class KeyEvent : public Event
{
    int keyCode = 0;
    //...
}

2. 与 union :

class Event
{
    struct KeyEvent
    {
        int keyCode = 0;
        //...
    }

    Type type; // Event type stored using an enum class

    union {
        KeyEvent keyEvent;
        MouseButtonEvent mouseButtonEvent;
        //...
    }
}

在这两种情况下,您都必须检查 Event::Type枚举,以了解发生了哪种事件。

当您使用继承时,您必须强制转换事件以获取它的值(例如,将 Event 转换为 KeyPressedEvent 以获取关键代码)。所以你必须将原始指针转换为需要的类型,这通常很容易出错。

当您使用 union 时,您可以简单地检索已发生的事件。但这也意味着内存中 union 的大小总是与其中包含的最大可能类一样大。这意味着可能会浪费大量内存。

现在的问题:

是否有任何论据可以使用一种方式而不是另一种方式?我应该浪费内存还是冒着错误转换的风险?

或者有没有我没有想到的更好的解决方案?

最后我只想通过例如一个 KeyEvent作为 Event .然后我想查看Event::Type使用枚举类。如果类型等于 Event::Type::Key我想获取关键事件的数据。

最佳答案

Event似乎比以行为为中心更以数据为中心,所以我会选择 std::variant :

using Event = std::variant<KeyEvent, MouseButtonEvent/*, ...*/>;
// or using Event = std::variant<std::unique_ptr<KeyEvent>, std::unique_ptr<MouseButtonEvent>/*, ...*/>;
// In you are concerned to the size... at the price of extra indirection+allocation

那么用法可能类似于
void Print(const KeyEvent& ev)
{
    std::cout << "KeyEvent: " << ev.key << std::endl;
}
void Print(const MouseButtonEvent& ev)
{
    std::cout << "MouseButtonEvent: " << ev.button << std::endl;
}

// ...

void Print_Dispatch(const Event& ev)
{
    std::visit([](const auto& ev) { return Print(ev); }, ev);
}

关于c++ - 事件系统 : Inheritance with type-casting or unions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62044850/

相关文章:

javascript - 多次调用 HTML5 视频结束事件

java - 您能否找到谁从 AWTEvent 对象对 EDT 进行了调用?

c++ - 有没有办法检查哪些命令符号被加载到 linux 中的应用程序中?

javascript - 在 HTML/Javascript 中处理由 ActiveX 控件的属性触发的事件

c++ - 推断成员函数的返回类型

java - 获取相对于框架的鼠标 X,Y 坐标

java - CloseHandler<Window> 和 Window.ClosingHandler() 在 IE 中的工作方式不同

c# - 字段System.MulticastDelegate._invocationCount不可用C#

c++ - C++ 中优雅的函数定义

c++ - 如何与 numeric_limits<int64_t>::min() 进行比较