事件监听器

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

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

posted on 2016-04-11 21:52  dongtshj  阅读(969)  评论(0编辑  收藏  举报