C++ 事件回调机制的几种实现方式

来源:互联网 发布:zookeeper nginx 集群 编辑:程序博客网 时间:2024/05/21 17:45

1、duilib中的CEventSource。以下代码摘自duilib,并且有一点改动。

delegate.h

#include <atlbase.h>class CDelegateBase{public:CDelegateBase(void* pObject, void* pFn);CDelegateBase(const CDelegateBase& rhs);virtual ~CDelegateBase();bool Equals(const CDelegateBase& rhs) const;bool operator() (void* param);virtual CDelegateBase* Copy() = 0;protected:void* GetFn();void* GetObject();virtual bool Invoke(void* param) = 0;private:void* m_pObject;void* m_pFn;};class CDelegateStatic : public CDelegateBase{typedef bool(*Fn)(void*);public:CDelegateStatic(Fn pFn) : CDelegateBase(NULL, pFn) { }CDelegateStatic(const CDelegateStatic& rhs) : CDelegateBase(rhs) { }virtual CDelegateBase* Copy() { return new CDelegateStatic(*this); }protected:virtual bool Invoke(void* param){Fn pFn = (Fn)GetFn();return (*pFn)(param);}};template <class O, class T>class CDelegate : public CDelegateBase{typedef bool (T::* Fn)(void*);public:CDelegate(O* pObj, Fn pFn) : CDelegateBase(pObj, &pFn), m_pFn(pFn) { }CDelegate(const CDelegate& rhs) : CDelegateBase(rhs) { m_pFn = rhs.m_pFn; }virtual CDelegateBase* Copy() { return new CDelegate(*this); }protected:virtual bool Invoke(void* param){O* pObject = (O*)GetObject();return (pObject->*m_pFn)(param);}private:Fn m_pFn;};template <class O, class T>CDelegate<O, T> MakeDelegate(O* pObject, bool (T::* pFn)(void*)){return CDelegate<O, T>(pObject, pFn);}inline CDelegateStatic MakeDelegate(bool(*pFn)(void*)){return CDelegateStatic(pFn);}class CEventSource{typedef bool(*FnType)(void*);public:~CEventSource();operator bool();void operator+= (CDelegateBase& d);void operator+= (FnType pFn);void operator-= (CDelegateBase& d);void operator-= (FnType pFn);bool operator() (void* param);protected:CSimpleArray<LPVOID> m_aDelegates;};
delegate.cpp

CDelegateBase::CDelegateBase(void* pObject, void* pFn){m_pObject = pObject;m_pFn = pFn;}CDelegateBase::CDelegateBase(const CDelegateBase& rhs){m_pObject = rhs.m_pObject;m_pFn = rhs.m_pFn;}CDelegateBase::~CDelegateBase(){}bool CDelegateBase::Equals(const CDelegateBase& rhs) const{return m_pObject == rhs.m_pObject && m_pFn == rhs.m_pFn;}bool CDelegateBase::operator() (void* param){return Invoke(param);}void* CDelegateBase::GetFn(){return m_pFn;}void* CDelegateBase::GetObject(){return m_pObject;}CEventSource::~CEventSource(){for (int i = 0; i < m_aDelegates.GetSize(); i++) {CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]);if (pObject) delete pObject;}}CEventSource::operator bool(){return m_aDelegates.GetSize() > 0;}void CEventSource::operator+= (CDelegateBase& d){for (int i = 0; i < m_aDelegates.GetSize(); i++) {CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]);if (pObject && pObject->Equals(d)) return;}m_aDelegates.Add(d.Copy());}void CEventSource::operator+= (FnType pFn){(*this) += MakeDelegate(pFn);}void CEventSource::operator-= (CDelegateBase& d){for (int i = 0; i < m_aDelegates.GetSize(); i++) {CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]);if (pObject && pObject->Equals(d)) {delete pObject;m_aDelegates.RemoveAt(i);return;}}}void CEventSource::operator-= (FnType pFn){(*this) -= MakeDelegate(pFn);}bool CEventSource::operator() (void* param){for (int i = 0; i < m_aDelegates.GetSize(); i++) {CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]);if (pObject && !(*pObject)(param)) return false;}return true;}
用法示例:

class ClsA{public:CEventSource EventA;void DoA() {EventA(NULL);}};bool HandleA(void* p){ATLTRACE(_T(__FUNCTION__));return true;}class ClsB{public:bool HandleA(void* p) {ATLTRACE(_T(__FUNCTION__));return true;}};int _tmain(int argc, _TCHAR* argv[]){ClsA a;ClsB b;a.EventA += MakeDelegate(&HandleA);a.EventA += MakeDelegate(&b, &ClsB::HandleA);a.DoA();a.EventA -= MakeDelegate(&HandleA);a.EventA -= MakeDelegate(&b, &ClsB::HandleA);return 0;}

2、boot::signals2
换了visual studio,boost代码需要重新编译,改天再写吧。


3、msvc支持的__event

[event_source(native)]class ClsA{public:__event bool EventA(int a, long b);void DoA() {__raise EventA(20, 100);}};[event_receiver(native)]class ClsB{public:bool OnEventA(int a, long b){ATLTRACE(_T(__FUNCTION__));return true;}};int _tmain(int argc, _TCHAR* argv[]){ClsA a;ClsB b;__hook(&ClsA::EventA, &a, &ClsB::OnEventA, &b);a.DoA();__unhook(&ClsA::EventA, &a, &ClsB::OnEventA, &b);return 0;}

0 0
原创粉丝点击