3

这是我的情况:

我有一个事件驱动系统,我所有的处理程序都从IHandler类派生,并实现一个onEvent(const Event &event)方法。现在,Event 是所有事件的基类,并且只包含枚举的事件类型。所有实际事件都来自它,包括EventKey事件,它有 2 个字段:(uchar) keyCode(bool) isDown

这是有趣的部分:我EventKey使用以下语法生成一个事件:

Event evt = EventKey(15, true);

我将它运送给处理程序:

EventDispatch::sendEvent(evt); // void EventDispatch::sendEvent(const Event &event);

(EventDispatch包含一个链接列表,并使用包含已发送事件的参数IHandlers调用它们的方法。onEvent(const Event &event)

现在实际的问题:

假设我希望我的处理程序轮询类型队列中的事件,Event我该怎么做?

  • 具有引用计数的动态指针听起来像是一个太大的解决方案。

  • 制作副本比听起来更困难,因为我只收到对基本类型的引用,因此每次我都需要检查事件的类型,向上转换EventKey然后制作副本以存储在队列中。听起来像是唯一的解决方案——但令人不快,因为我需要了解每一种类型的事件,并且必须检查收到的每一个事件——这听起来像是一个糟糕的计划。

  • 我可以动态分配事件,然后发送指向这些事件的指针,如果需要,将它们排入数组中 - 但除了引用计数之外 - 我如何能够跟踪该内存?你知道有什么方法可以实现一个不会干扰用户的非常轻的参考计数器吗?

您认为这个设计的一个好的解决方案是什么?

4

3 回答 3

4

好的,首先,这条线没有做你认为它做的事情:

Event evt = EventKey(15, true);

这将创建一个临时 EventKey 对象,将其切片到基类 Event,然后调用 Event 复制构造函数。EventKey 类中保存的所有实际数据都将丢失。如果你想要多态性,你想要使用动态对象或引用。

至于您的实际问题,我建议您重新设计并为每种事件类型设置单独的队列(以及单独的处理程序)...... onEventA、onEventB 等。

于 2010-06-01T06:14:51.810 回答
1

意见:选择引用计数选项。使用 boost::shareed_ptr 和 boost::dynamic_pointer_cast 来确定实际类型。

于 2010-06-01T05:35:34.363 回答
1

除非您共享事件对象,否则您实际上并不需要引用计数。如果您在任何给定时间只有一个所有者 - 在您的情况下,它通常是事件队列 - 那么您只需要使用适当的容器。

如果您的实现已经部分实现了 C++0x(例如最近的 g++ 版本或 VC++2010),那么您可以简单地使用std::queue<std::unique_ptr<Event>>. 如果std::unique_ptr不可用,您可以使用Boost Pointer Container libraryboost::ptr_deque或其他一些合适的容器。

于 2010-06-01T05:53:38.377 回答