c++ - 回调参数 C++ 中的协方差

标签 c++ class c++11 inheritance struct

好的,我已经创建了一个系统来监听和处理事件,如下所示。我创建了一个事件结构和几个更具体的结构来保存事件数据。我还为接收事件数据的监听器创建了一个 typedef。内部事件处理程序接收事件并在该事件的适当 vector 中运行所有用户定义的监听器。但是,由于 Event 类仅包含 EventType,因此特定事件数据被切掉了。有没有办法解决这个问题,这样我就不必重写几乎所有的代码。我曾尝试通过引用传递事件,但这并没有解决问题。这是到目前为止的代码...

编辑:我知道我可以使用 static_cast 来使用事件中的其他数据,但是由于我正在尝试为开发人员创建一个简单的 API,所以我不想强制用户在每个监听器中使用 static_cast。

结构

struct Event {
    EventType type;
};
struct MouseEvent : Event {
    int x;
    int y;
    bool down;
    uint8_t which;
};
typedef function<void(MYCLASS&, Event&)> Listener;
typedef vector<Listener*> Listeners;

处理程序

void MYCLASS::eventHandler(Event& event, Listeners* listeners) {
  for(auto it = listeners->begin(); it != listeners->end(); ++it) {
    (**it)(*this,event);
  }
}

示例用户定义的监听器

    instance.addListener(MOUSEMOVE, [](MYCLASS& a, Event& e) {
        cout << e.x << endl; //THIS LINE DOES NOT WORK
    });

最佳答案

受到积极反馈的鼓舞,我在这里发布我的答案。

主要思想是分别处理每个回调类型,例如鼠标和键盘。

instance.addMouseListener([](MYCLASS& a, MouseEvent& e) {
    cout << e.x << endl;
});
instance.addKeyboardListener([](MYCLASS& a, KeyboardEvent& e) {
    cout << e.button << endl; 
});

它有点凌乱,但它运行良好(至少对于我的游戏而言)。
而且,我相信这是一个标准的解决方法。
(参见:addMouseListener for a JPanelSDL Mouse Click)

但我更喜欢另一种方式。它可能适合也可能不适合你。
我创建了一个鼠标/键盘实例,并将它们视为全局变量。
然后用户可以查询它:-

//in game loop : e.g. System_UpdateRocket.h
MousePtr* mouse=getMouseGlobal();
KeyboardPtr* keyboard=getKeyboardGlobal();
if(mouse->getMouseMovementDelta().x < 0 &&        
  keyboard->justPressThisFrame(KEYBOARD::SPACE_BUTTON)){
     //do something e.g. myRocket->pewPew();
}

在这种方法中,需要有一个库级别的中央系统,它在每个时间步更新每个类似全局的实例(如 MousePtr*)。

关于c++ - 回调参数 C++ 中的协方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57532753/

相关文章:

c++ - std::thread - 命名你的线程

c++ - 没有匹配函数调用 ‘begin(int**&)’

c++ - 多重定义 C++

c++ - Boost.Spirit,如何扩展xml解析?

Java - 如何使用类文件?

python - 如何修改类方法?

c++ - 带有模板参数的自定义 C++ 异常

c++ - 如何设置一个元表以从另一个元表继承,同时将用户数据更改为另一种类型?

c++ - 类(class)成员的顺序会影响访问速度吗?

c++ - 在哪里实现我的 MFC DLL 函数?