0

我正在编写一个Window传播不同类型事件的类,列在

enum Event {WINDOW_ClOSE=0x1, WINDOW_REDRAW=0x2, MOUSE_MOVE=0x4, ...}; 

到已注册通知窗口的对象。对于每种类型的事件,我都有一个抽象类,任何对象都必须扩展它以允许通知。为了对一个事件做出反应MOUSE_MOVE,我的对象将继承自MouseMoveListener,它有一个process_mouse_move_event()由 调用的方法Window。可以通过扩展这些类中的多个来组合侦听许多事件,这些类都继承自基EventListener类。要注册一个对象,我会调用

void Window::register(EventListener* object, int EventTypes)
{
    if(EventTypes&WINDOW_CLOSE)
       /* dynamic_cast object to WindowCloseListener*, add to internal list of all
          WindowCloseListeners if the cast works, else raise error */

    if(EventTypes&MOUSE_MOVE)     
       /* dynamic_cast object to MouseMoveListener*, add to internal list of all
          MouseMoveListeners if the cast works, else raise error */

    ...
} 

这很好用,但我的抱怨是它EventListener完全是的,而且我觉得代码很臭。我知道我可以通过EventListener完全删除并为每种类型的事件单独设置来避免这种Window::register情况,但我觉得这会不必要地炸毁我的界面(特别是因为其他方法register可能会出现同样的问题)。所以我想我正在寻找答案,要么说:

  • “你可以按照你的方式继续做,因为......”或

  • “无论如何都要引入单独的Window::register方法,因为......”或者当然

  • “你做错了,你应该……”。

编辑:

来自 Igors 评论中的链接:我上面所做的只有在至少有一个虚拟成员( EventListener例如虚拟析构函数)时才有效,因此该类在技术上并非完全为空。

编辑2:

我过早地接受了 nm 的解决方案作为“我做错了”的类型之一。但是,它属于第二种。即使我可以EventListener->register(Window&)多态调用,也Window需要实现一个高度冗余的接口(就声明的方法而言),它允许EventListeners注册选择性通知。这等效于我上面描述的替代解决方案,只是EventListener无缘无故地额外引入了该类。总之,规范的答案似乎是:

不要dynamic_cast为了避免声明许多类似的函数而做+空基类,这会在以后维护代码时伤害您​​。编写许多函数。

编辑 3:

我找到了一个令我满意的解决方案(使用模板)。它不再使用空基类,也没有出现 nm 指出的维护问题

4

2 回答 2

2
object->registerWindow (this, EventTypes);

当然,您需要registerWindow为所有EventListener继承人实施。让他们检查与他们相关的事件类型。

更新

如果这意味着您需要重新设计代码,那么您需要重新设计代码。为什么会这样?因为dynamic_cast不是做开关类型的正确方法。这不是一种正确的方法,因为每次在层次结构中添加类时,都需要检查并可能更新旧代码中的所有动态转换开关。这很快就会变得非常混乱和不可维护,这正是虚函数被发明的原因。

如果您使用虚拟功能进行切换类型,则每次更改层次结构时,您都必须……什么都不做。虚拟调用机制将处理您的更改。

于 2013-10-16T18:49:59.737 回答
0

这就是我最终做的事情:

template <int EventType> void register_(EventListener<EventType> Listener)
{
    // do stuff with Listener, using more templates
};

事实证明,静态多态更适合我的需求——我只是想避免写

register_mouse_motion_event(...)
register_keyboard_event(...)

等等。这种方法也很好地消除了对空基类的需要。

于 2013-10-17T07:59:00.700 回答