0

我有一个简单的事件处理系统,它给我带来了问题。要使用它,我从类继承EventHandler。然后构造函数在构造时注册每个对象。

这是EventHandler的构造函数:

EventHandler::EventHandler()
{
   EventDispatcher::getInstance().registerListener(this);
}

这调用了将其存储在向量中EventDispatcher的成员函数。registerListener()

void EventDispatcher::registerListener(EventHandler* listener) 
{
   mListenerList.push_back(listener);
}

mLisernerList 在哪里看起来像:

vector<EventHandler*> mListenerList;

EventDispatcher只需调用向量的每个sendEvent()元素上的 来通知它事件。

让我举一个例子来说明我的问题。假设我的类Buttons继承自EventHandler. 我将在堆上创建按钮对象,然后将指向所有按钮的智能指针放在一个向量中。

vector<unique_ptr<Buttons>> mButtons;   
mButtons.push_back(unique_ptr<Buttons>(new Button()));

发生的事情是我最终得到了unique_ptrmButtons 中的 s 向量和 mListenerList 中指向相同动态分配的 Button 对象的原始指针向量。我不希望智能指针和原始指针指向同一个对象。

理想情况下,我希望 mButtons 中的shared_ptrs 向量和 mListenerList 中的s 向量weak_ptr指向动态分配的 Button 对象,同时允许 EventHandler 在创建时注册每个对象。这可能吗?

4

2 回答 2

1
class EventHandler {
private
    EventHandler(); //make the constructors protected, also in derived when possible

    template<class T, class...Us> //and make this function a friend
    friend std::shared_ptr<EventHandler> make_event(Us...us);
};
//this is the function you use to construct Event objects
template<class T, class...Us>
std::shared_ptr<T> make_event(Us...us)
{
    auto s = std::make_shared<T>(std::forward<Us>(us)...);
    EventDispatcher::getInstance().registerListener(s);
    return s;
}

这将调用 EventDispatcher 的 registerListener() 成员函数,该函数将其存储在向量中。

void EventDispatcher::registerListener(std::weak_ptr<EventHandler> listener) 
{
   mListenerList.push_back(listener);
}

mLisernerList 在哪里看起来像:

vector<std::weak_ptr<EventHandler>> mListenerList;

EventDispatcher 只需在向量的每个元素上调用 sendEvent() 即可将事件通知它。

让我举一个例子来说明我的问题。假设我的类 Buttons 继承自 EventHandler。我将在堆上创建按钮对象,然后将指向所有按钮的智能指针放在一个向量中。

vector<std::shared_ptr<Buttons>> mButtons;   
mButtons.push_back(make_event<Buttons>());
于 2014-05-06T17:01:42.330 回答
1

你不能天真地使用std::shared_ptr; 有一些特殊的支持可能会允许它,但它过于复杂,几乎可以肯定在这里不合适;an EventDispatcher通常不可能“拥有” an EventHandler

这里真正的问题是为什么你要在这里使用智能指针?在其EventHandler构造函数中注册,并在其析构函数中取消注册。中的指针 EventDispatcher纯粹用于导航。同样的事情可能适用于mButtons,尽管有些设计可能并非如此。(我倾向于对 的向量持怀疑态度unique_ptr。这取决于向量所在的位置,但据我所知,访问实际指针所需的额外复杂性超过了手动处理删除的复杂性。)

于 2014-05-06T17:15:41.750 回答