Tôi đã làm điều này với std :: function và std :: bind ..
Tôi đã viết lớp EventManager này lưu trữ một vectơ của các trình xử lý trong một bản đồ không có thứ tự ánh xạ các loại sự kiện (chỉ là const unsigned int, tôi có một enum không gian tên lớn trong số đó) vào một vector trình xử lý cho loại sự kiện đó.
Trong lớp EventManagerTests của mình, tôi đã thiết lập một trình xử lý sự kiện, như sau:
auto delegate = std::bind(&EventManagerTests::OnKeyDown, this, std::placeholders::_1);
event_manager.AddEventListener(kEventKeyDown, delegate);
Đây là hàm 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;
}
Đây là định nghĩa kiểu EventHandler:
typedef std::function<void(Event *)> EventHandler;
Sau đó, quay lại EventManagerTests :: RaiseEvent, tôi thực hiện điều này:
Engine::KeyDownEvent event(39);
event_manager.RaiseEvent(1, (Engine::Event*) & event);
Đây là mã cho 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);
}
);
}
}
Những công việc này. Tôi nhận được cuộc gọi trong EventManagerTests :: OnKeyDown. Tôi phải xóa các vectơ đến thời gian dọn dẹp, nhưng một khi tôi làm điều đó thì không có rò rỉ. Việc tạo một sự kiện mất khoảng 5 micro giây trên máy tính của tôi, vào khoảng năm 2008. Không chính xác là siêu nhanh, nhưng. Đủ công bằng miễn là tôi biết điều đó và tôi không sử dụng nó trong mã cực kỳ nóng.
Tôi muốn tăng tốc nó bằng cách cuộn std :: function và std :: bind của riêng mình, và có thể sử dụng một mảng mảng thay vì một bản đồ vectơ không có thứ tự, nhưng tôi chưa tìm ra cách lưu trữ một hàm thành viên con trỏ và gọi nó từ mã không biết gì về lớp được gọi. Câu trả lời của Eyelash trông rất thú vị ..