这是我的情况:
我有一个事件驱动系统,其中所有处理程序都派生自 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
的链接列表code> 并使用包含发送事件的参数调用其 onEvent(const Event &event)
方法,
现在实际的问题是:
假设我希望我的处理程序轮询 事件
,我该怎么做?
您认为这个设计的一个好的解决方案是什么?
Here is my situation:
I have an event driven system, where all my handlers are derived from IHandler
class, and implement an onEvent(const Event &event)
method. Now, Event is a base class for all events and contains only the enumerated event type. All actual events are derived from it, including the EventKey
event, which has 2 fields: (uchar) keyCode
and (bool) isDown
.
Here's the interesting part: I generate an EventKey
event using the following syntax:
Event evt = EventKey(15, true);
and I ship it to the handlers:
EventDispatch::sendEvent(evt); // void EventDispatch::sendEvent(const Event &event);
(EventDispatch
contains a linked list of IHandlers
and calls their onEvent(const Event &event)
method with the parameter containing the sent event.
Now the actual question:
Say I want my handlers to poll the events in a queue of type Event
, how do I do that?
-
Dynamic pointers with reference counting sound like too big of a solution.
-
Making copies is more difficult than it sounds, since I'm only receiving a reference to a base type, therefore each time I would need to check the type of event, upcast to EventKey
and then make a copy to store in a queue. Sounds like the only solution - but is unpleasant since I would need to know every single type of event and would have to check that for every event received - sounds like a bad plan.
-
I could allocate the events dynamically and then send around pointers to those events, enqueue them in the array if wanted - but other than having reference counting - how would I be able to keep track of that memory? Do you know any way to implement a very light reference counter that wouldn't interfere with the user?
What do you think would be a good solution to this design?
发布评论
评论(3)
好的,首先,这一行代码并不像您想象的那样:
这会创建一个临时的 EventKey 对象,将其切片到基类 Event,然后调用 Event 复制构造函数。 EventKey 类中保存的所有实际数据都会丢失。如果您想要多态性,则需要使用动态对象或引用。
至于您的实际问题,我建议您重新设计并为每种事件类型拥有单独的队列(因此也有单独的处理程序)... onEventA、onEventB 等。
Ok, first off, this line doesn't do what you think it does:
This creates a temporary EventKey object, slices it to the base class Event, then calls the Event copy constructor. All actual data kept in the EventKey class is lost. If you want polymorphism, you want to use either dynamic objects or references.
As for your actual question, I'd recommend you redesign and have separate queues (and thus separate handlers) for each event type... onEventA, onEventB, etc.
意见:选择引用计数选项。使用 boost::shareed_ptr 和 boost::dynamic_pointer_cast 来确定实际类型。
Opinion: choose the reference counting option. Use boost::shareed_ptr, and boost::dynamic_pointer_cast to determine actual type.
除非您共享事件对象,否则您实际上并不需要引用计数。如果您在任何给定时间只有一个所有者(在您的情况下,通常是事件队列),那么您只需要使用适当的容器即可。
如果您的实现已经部分实现了 C++0x(例如最近的 g++ 版本或 VC++2010),那么您可以简单地使用
std::queue>
。如果std::unique_ptr
不可用,您可以使用boost::ptr_deque
或 Boost 指针容器库。You don't really need reference counting unless you share your event objects. If you only have one owner at any given time - in your case, it would normally be the event queue - then you simply need to use an appropriate container.
If your implementation has partially implemented C++0x already (e.g. recent g++ versions, or VC++2010), then you can simply use
std::queue<std::unique_ptr<Event>>
. Ifstd::unique_ptr
is not available, you can useboost::ptr_deque
or some other suitable container from the Boost Pointer Container library.