- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个 Window
类,它传播不同类型的事件,列在
enum Event {WINDOW_ClOSE=0x1, WINDOW_REDRAW=0x2, MOUSE_MOVE=0x4, ...};
已注册窗口通知的对象。对于每种类型的事件,我都有一个抽象类,任何对象都必须扩展该抽象类才能允许通知。例如,为了响应 MOUSE_MOVE
事件,我的对象将从 MouseMoveListener
继承,它有一个 process_mouse_move_event()
方法,该方法由 窗口
。可以通过扩展这些类中的多个来组合监听多个事件,这些类都继承自 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:
我过早地接受了 n.m. 的解决方案作为“我做错了”的类型之一。然而,它属于第二种。即使我可以多态地调用 EventListener->register(Window&)
,Window
也需要实现一个高度冗余的接口(interface)(就声明的方法而言),它允许 EventListeners
注册选择性通知。这等同于我上面描述的替代解决方案,只是无缘无故地额外引入了 EventListener
类。总之,规范的答案似乎是:
不要为了避免声明很多类似的函数而做dynamic_cast
+ 空基类,这会在以后维护代码时伤害到你。编写许多函数。
编辑 3:
我找到了一个令我满意的解决方案(使用模板)。它不再使用空基类,也不会出现 n.m. 指出的维护问题。
最佳答案
object->registerWindow (this, EventTypes);
当然你需要为所有的EventListener
继承者实现registerWindow
。让他们检查与他们相关的事件类型。
更新
如果这意味着您需要重新设计代码,那么您需要重新设计代码。为什么会这样?因为 dynamic_cast
不是执行类型切换的正确方法。这不是一种正确的方法,因为每次在层次结构中添加一个类时,您都需要遍历并可能更新旧代码中的所有 switches-by-dynamic-cast。这很快就会变得非常困惑和难以维护,这正是虚函数被发明的原因。
如果您使用虚函数执行开关类型,则每次更改层次结构时都必须...什么都不做。虚拟调用机制将处理您的更改。
关于c++ - 在此示例中使用空基类是否合理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19411053/
仍在掌握 C++ 类的窍门,我想知道实现此目的的最高效的运行时方法是什么: 我有一个派生类,我想实例化一次(在编译时已知),但我想将指针类型转换为基类指针并将其传递给我的程序的其余部分使用。这样,如果
我是一名优秀的程序员,十分优秀!