我正在尝试用C ++编写一个非常简单的事件或消息类。我希望事件保持发生的时间和一些特定于事件类型的数据。 我现在所拥有的是以下内容
class EventData{
public:
virtual ~EventData(void) = 0;
};
struct Event{
Event(EventType type, Time time, EventData *data = nullptr):
type_(type), time_(time), data_(data)
{}
~Event(void){
if(data_) delete data_;
}
//Disable copying, event memory will be managed by EventManager
Event(const Event& other) = delete;
const EventType type_;
const Time time_;
const EventData *data_;
};
在我的主循环中,我有类似的东西,
bool running = true;
while(running){
const Event* nextEvent = evtManager.getNextEvent();
switch(nextEvent.type_){
case EVT_A:
const EventAData* data = static_cast<EventAData*>(nextEvent.data_);
//do stuff
break;
}
...
case EVT_END:
running = false;
break;
}
}
那么问题是,是否有更有效的方法,即使用模板。另一个问题是有人可能会意外地提供错误的EventType
,EventData
对,在这种情况下static_cast
会失败。
我应该注意,我希望这个Event
类尽可能快,特别是访问time_
成员变量。
答案 0 :(得分:1)
typeid
区分类型。答案 1 :(得分:1)
您可以使用继承,而不是使用模板。
事件可以是一个带有一个成员变量_time的抽象基类。使用简单的访问器方法(可能内联)或通过使_time成为公共成员变量,访问_time成员变量将很快。使用访问器方法几乎总是更好。访问速度非常快,如果需要,访问器将允许您灵活地在稍后的某个时间点更改内部时间表示。
示例中的EventType枚举实际上描述了Event的所有可能子类。如果要为EventType中的每个条目创建抽象基类Event的具体子类,则实际上不需要EventType枚举。子类标识事件类型。所有子类的构造函数可以是唯一的,每个子类都使用不同的参数。每个子类都可以为其成员变量提供访问器。这些额外的构造函数参数和访问器可以替换EventData类。
最后,您的主循环有两种选择。首先,您可以多态地处理当前在每个case语句中完成的处理。 Event基类可以有一个名为“processEvent()”的纯虚函数,每个子类都可以覆盖它。如果可以,您可以使用简单的函数调用替换switch语句:
nextEvent->processEvent();
其次,如果这不可行,您可以使用RTTI将nextEvent变量从Event指针向下转换为相应子类的指针。然后,您可以调用特定于子类的访问器来执行与您当前正在执行的操作类似的处理。