ฉันทำสิ่งนี้ด้วย std :: function และ std :: bind ..
ฉันเขียนคลาส EventManager นี้ซึ่งเก็บเวกเตอร์ของตัวจัดการใน unordered_map ที่แมปประเภทเหตุการณ์ (ซึ่งเป็นเพียง int ที่ไม่ได้ลงนามฉันมี enum ขนาดใหญ่ที่กำหนดขอบเขตเนมสเปซ) ไปยังเวกเตอร์ของตัวจัดการสำหรับประเภทเหตุการณ์นั้น
ในคลาส 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 ของเวกเตอร์ แต่ฉันยังไม่ได้หาวิธีจัดเก็บฟังก์ชันสมาชิก ตัวชี้และเรียกจากรหัสที่ไม่รู้อะไรเลยเกี่ยวกับคลาสที่ถูกเรียก คำตอบของขนตาดูน่าสนใจมาก ..