我用 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,但我还没有完全弄清楚如何存储成员函数指针并从对所调用的类一无所知的代码中调用它。睫毛的答案看起来很有趣..