事件监听器
游戏开发中经常会用到这玩意。
说到事件监听器,必须要说C++的一个知识点:类的成员函数指针。
事件监听器要干的事情:就是把一个类的成员函数指针相关信息保存下来,等到需要调用这个成员函数的时候再来用它。
而类的成员函数指针是一个不完整的指针,它不像静态函数的指针或者普通函数的指针可以直接调用,想要调用它还需要被绑定于某个对象的地址上来调用这个指针。
先构造一个类专门用来保存这个成员函数指针的相关信息,并且重载函数的调用运算符“()”;因为每个类的成员函数的指针类型都是唯一的,所以我们使用类模板来保存每一个类的成员函数指针。
class EventBase { public: virtual void operator()(void) = 0; }; template <class T, class F> class Event : public EventBase { public: Event(T p, F f) :ptr(p), func(f){}; virtual void operator()(void){ (ptr->*func)(); }; private: T ptr; F func; };
事件监听器是一个单例,主要功能就是注册事件和移除事件以及触发事件:
class EventListener { public: template <class T, class F> void RegistEvent(std::string evt_id, T p, F f) { EventBase* evt = new Event<T, F>(p, f); m_evt_map[evt_id] = evt; } void RemoveEvent(std::string evt_id) { if (m_evt_map.find(evt_id) != m_evt_map.end()) { EventBase* evt = m_evt_map[evt_id]; delete evt; m_evt_map.erase(evt_id); } } void Trigger(std::string evt_id) { if (m_evt_map.find(evt_id) != m_evt_map.end()) { EventBase* evt = m_evt_map[evt_id]; (*evt)(); } } private: std::map<std::string, EventBase*> m_evt_map; public: static EventListener* Instance() { if (m_instance == NULL) m_instance = new EventListener(); return m_instance; } private: static EventListener* m_instance; private: EventListener(){}; }; EventListener* EventListener::m_instance = NULL;
测试代码如下:
class TestScene { public: void Init() { Func1(); } void Func1() { EventListener::Instance()->RegistEvent("Call Func2", this, &TestScene::Func2); } void Func2() { std::cout << "TestScene::Func2"<<std::endl; } private: }; int _tmain(int argc, _TCHAR* argv[]) { TestScene ts; ts.Init(); EventListener::Instance()->Trigger("Call Func2");
EventListener::Instance()->Trigger("Call Func2");就等同于ts.Func2
好了,暂时就这么多了。
类的成员函数指针的补充:
class T { public: void Test(); };
那么T的成员函数Test的指针类型就是void (T::*)(void),成员函数Test的地址就是&T::Test
(把C++11中匿名函数作为回调函数)
我们只要重载 EventListener的RegistEvent成员函数即可:
void RegistEvent(std::string evt_id, std::function<void(void)> func) { m_evt_func[evt_id] = func; }
其它移除事件和触发事件的函数实现方法类似。
当然EventListener类需要增加一个容器m_evt_func专门用来容纳匿名函数注册的事件。
它的类型是std::map<std::string, std::function<void(void)> >.
std::function是一个类模板,专门用来存放各种可调用对象的。在这里表示的是一个返回类型是void形参是void的可调用对象。