zoukankan      html  css  js  c++  java
  • 事件监听器

    游戏开发中经常会用到这玩意。

    说到事件监听器,必须要说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的可调用对象。

  • 相关阅读:
    jquery堆栈与队列
    类数组转成数组对象
    python基础教程总结8——特殊方法,属性,迭代器,生成器,八皇后问题
    python基础教程总结7——异常
    python基础教程总结6——类
    python基础教程总结5——函数
    python基础教程总结4—基本语句
    python——动态类型
    python基础教程总结3—字典
    python基础教程总结2——字符串
  • 原文地址:https://www.cnblogs.com/dongerlei/p/5380340.html
Copyright © 2011-2022 走看看