具有多种类型和多态处理程序的 C++ 事件队列

问题描述 投票:0回答:0

我正在尝试在 C++ 中创建一个异步事件处理系统,其中有一个全局事件队列。我试图让这个事件队列使用一个基本接口来允许将任何类型的事件插入到队列中。一切正常,除了我在将事件委托给正确的处理函数时遇到问题。理想情况下,一个类可以扩展 EventHandler 类并使其重载的 handle() 方法正确处理不同类型的事件。我不确定我是否以正确的方式进行此操作。下面是我的简单示例,实际上事件队列将是一个单例,多个线程可以发挥作用。

#include <iostream>
#include <queue>

// Forward declarations
class EventQueue;
class EventInterface;
class EventHandler;
template <class T> class Event;

// Event data types
struct Data {
    int i;
};

struct Data2 {
    int i;
};

class EventQueue
{
    public: 
        EventQueue() {}
        ~EventQueue() {}
        bool addEvent(EventInterface* event) {
            queue_.push(event);
            return true;
        }

        bool hasEvent() {
            return !queue_.empty();
        }

        EventInterface* getEvent() {
            EventInterface* event = queue_.front();
            queue_.pop();
            return event;
        }

    private:
        std::queue<EventInterface*> queue_;
};

class EventInterface
{
public:
    EventInterface() {}
    virtual ~EventInterface() {}
};

template<class T> class Event: public EventInterface
{
public:
    Event(T data, EventQueue* queue): data_(data), queue_(queue) {}
    ~Event() {}

    void raise() {
        queue_->addEvent(this);
    }

    T getData() { return data_; }

private:
    T data_;
    EventQueue* queue_;
};

class EventHandler {
    public: 
        EventHandler(EventQueue* eventQueue) : eventQueue_(eventQueue) {}

        ~EventHandler() {}

        virtual void handleEvent(EventInterface* event) {
            std::cout << "EventHandler::handleEvent(Base): called" << std::endl;
        }

    private:
        EventQueue* eventQueue_;
};

class MyClass: public EventHandler {
    public: 
        MyClass(EventQueue* eventQueue): EventHandler(eventQueue) {}

        ~MyClass() {}

        void handleEvent(Event<Data>* event) {
            std::cout << "MyClass::handleEvent(Data) called" << std::endl;
        }

        void handleEvent(Event<Data2>* event) {
            std::cout << "MyClass::handleEvent(Data2) called" << std::endl;
        }
    private:
};

class EventListener {
    public:
        EventListener(EventQueue* eventQueue, EventHandler* handler)
            : eventQueue_(eventQueue), handler_(handler) {}
        ~EventListener() {}

        void process() {
            if(eventQueue_->hasEvent()) {
                EventInterface* event = eventQueue_->getEvent();
                handler_->handleEvent(event);
            }
        }

    private:
        EventQueue* eventQueue_;

        EventHandler* handler_;
};

int main() {
    EventQueue* eventQueue = new EventQueue();

    // Create event handler
    MyClass* myClass = new MyClass(eventQueue);
    EventListener* listener = new EventListener(eventQueue, myClass);

    // Raise events
    Event<Data> event(Data{1}, eventQueue);
    event.raise();

    Event<Data2> event2(Data2{1}, eventQueue);
    event2.raise();

    // Process events
    listener->process();
    listener->process();

    // Clean up
    delete listener;
    delete myClass;
    delete eventQueue;

    return 0;
}

示例程序输出:

EventHandler::handleEvent(Base): called 
EventHandler::handleEvent(Base): called

这里的问题很明显,因为派生类 MyClass 没有指定重载的 handleEvent(EventInterface*) 方法,而是调用了基类方法。添加该方法使 MyClass 处理事件,但我希望它由正确类型化的 handleEvent() 方法动态处理。我知道可以在派生类重载的 handleEvent(EventInterface*) 方法中进行 dynamic_cast 检查,然后调用适当的处理程序。我想知道是否有一种方法可以理想地将尽可能多的复杂性从派生类 MyClass 移开(因此最好避免这种逻辑)。我计划将它用作一个库,并且希望尽可能地减少客户端的复杂性。

也许这是不可行的,我必须忍受它,我不确定。我目前正在使用 clang 在 M1 mac 上使用 c++14 进行编译。我不需要在特定的 C++ 版本上进行编译。归根结底,这只是一个有趣的探索项目。

提前致谢。

c++ inheritance polymorphism
© www.soinside.com 2019 - 2024. All rights reserved.