简体   繁体   English

用C ++编写一个非常简单的事件类

[英]Writing a very simple event class in C++

I'm trying to write a really simple event or message class in C++. 我试图用C ++编写一个非常简单的事件或消息类。 I want the event to hold the time of occurrence and some data which are specific to the event type. 我希望事件保留发生时间以及一些特定于事件类型的数据。 What I have at the moment is the following 我现在所拥有的是以下


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_;
};

In my main loop, I have something like this, 在我的主循环中,我有这样的事情,


bool running = true;
while(running){
    const Event* nextEvent = evtManager.getNextEvent();
    switch(nextEvent.type_){
    case EVT_A:
        const EventAData* data = static_cast&ltEventAData*>(nextEvent.data_);
        //do stuff
        break;
    }
    ...
    case EVT_END:
        running = false;
        break;
    }
}

The question then is if there is a more efficient way of doing this, ie with templates. 然后的问题是,是否有更有效的方法来做到这一点,即使用模板。 the other problem is that someone could accidentally give the wrong EventType , EventData pair, in which case the static_cast will fail. 另一个问题是,有人可能会意外给出错误的EventTypeEventData对,在这种情况下, static_cast将失败。

I should note that I want this Event class to be as fast as possible, especially the access to the time_ member variable. 我应该注意,我希望Event类尽可能快,尤其是对time_变量的访问。

  1. There is no need to check whether the pointer is null before deleting it. 删除指针之前无需检查指针是否为空。
  2. You are trying to perform type-erasing, and then perform different tasks depending on the type you just erased. 您试图执行类型擦除,然后根据刚擦除的类型执行不同的任务。 It's inefficient. 效率低下。 Look into boost::variant instead, it seems that it's exactly what you need. 看看boost :: variant,似乎正是您所需要的。
  3. If you insist on using this method, you should use typeid to discriminate between types. 如果您坚持使用此方法,则应使用typeid来区分类型。

Instead of using templates, you could use inheritance. 除了使用模板,您还可以使用继承。

Event can be an abstract base class with one member variable, _time. 事件可以是具有一个成员变量_time的抽象基类。 Accessing the _time member variable will be fast with a simple accessor method (possibly inlined) or by making _time a public member variable. 使用简单的访问器方法(可能是内联的)或通过将_time设为公共成员变量,可以快速访问_time成员变量。 You're almost always better off using an accessor method. 使用访问器方法几乎总是更好。 The access will be plenty fast, and the accessor will allow you the flexibility to change your internal representation of the time at some later point if the need arises. 访问将非常快,访问器将使您可以灵活地在需要时在以后的某个时间更改时间的内部表示形式。

The EventType enum in your example really describes all the possible subclasses of Event. 您的示例中的EventType枚举实际上描述了Event的所有可能的子类。 If you were to create a concrete subclass of the abstract base class Event for every entry in EventType, you really wouldn't need the EventType enum. 如果要为EventType中的每个条目创建抽象基类Event的具体子类,则实际上不需要EventType枚举。 The subclass identifies the event type. 子类标识事件类型。 The constructors for all the subclasses could be unique, each one taking different parameters. 所有子类的构造函数都可以是唯一的,每个构造函数采用不同的参数。 Each subclass could provide accessors for its member variables. 每个子类都可以为其成员变量提供访问器。 These additional constructor parameters and accessors could replace the EventData class. 这些其他构造函数参数和访问器可以替换EventData类。

Finally, you have two alternatives for your main loop. 最后,对于主循环,您有两种选择。 First, you might treat the processing currently done in each case statement polymorphically. 首先,您可以对每个case语句中当前完成的处理进行多态处理。 The Event base class could have a pure virtual function called “processEvent()” which each subclass could override. Event基类可以具有一个称为“ processEvent()”的纯虚函数,每个子类都可以覆盖该虚函数。 If that is possible, you could replace the switch statement with a simple function call: 如果可能的话,可以用一个简单的函数调用替换switch语句:

nextEvent->processEvent();

Second, if that isn't feasible, you could use RTTI to downcast the nextEvent variable from an Event pointer to a pointer of the appropriate subclass. 其次,如果这不可行,则可以使用RTTI将nextEvent变量从Event指针向下转换为适当的子类的指针。 You could then call the subclass-specific accessors to perform processing that's similar to what you're currently doing. 然后,您可以调用特定于子类的访问器来执行与您当前正在执行的处理类似的处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM