我用std :: function和std :: bind做到了。
我写了这个EventManager类,将处理程序的向量存储在unordered_map中,该映射器将事件类型(只是const unsigned int,我有一个很大的作用域范围的枚举)映射到该事件类型的处理程序向量。
在我的EventManagerTests类中,我设置了一个事件处理程序,如下所示:
auto delegate = std::bind(&EventManagerTests::OnKeyDown, this, std::placeholders::_1);
event_manager.AddEventListener(kEventKeyDown, delegate);
这是AddEventListener函数:
std::vector<EventHandler>::iterator EventManager::AddEventListener(EventType _event_type, EventHandler _handler)
{
if (listeners_.count(_event_type) == 0)
{
listeners_.emplace(_event_type, new std::vector<EventHandler>());
}
std::vector<EventHandler>::iterator it = listeners_[_event_type]->end();
listeners_[_event_type]->push_back(_handler);
return it;
}
这是EventHandler类型定义:
typedef std::function<void(Event *)> EventHandler;
然后回到EventManagerTests :: RaiseEvent,我这样做:
Engine::KeyDownEvent event(39);
event_manager.RaiseEvent(1, (Engine::Event*) & event);
这是EventManager :: RaiseEvent的代码:
void EventManager::RaiseEvent(EventType _event_type, Event * _event)
{
if (listeners_.count(_event_type) > 0)
{
std::vector<EventHandler> * vec = listeners_[_event_type];
std::for_each(
begin(*vec),
end(*vec),
[_event](EventHandler handler) mutable
{
(handler)(_event);
}
);
}
}
这可行。我在EventManagerTests :: OnKeyDown中接到电话。我必须删除引导程序清理时间,但是一旦执行,就不会泄漏。在我的计算机上,引发一个事件大约需要5微秒,大约是2008年。只要我知道就足够公平,而且我不会在超热代码中使用它。
我想通过滚动自己的std :: function和std :: bind来加快速度,也许使用数组数组而不是矢量的unordered_map,但我还没有弄清楚如何存储成员函数指针并从对被调用类一无所知的代码中调用它。睫毛的答案看起来很有趣。