gpt4 book ai didi

c++ - 在此示例中使用空基类是否合理?

转载 作者:行者123 更新时间:2023-11-28 03:07:10 25 4
gpt4 key购买 nike

我正在编写一个 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com