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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hyhnoproblem/article/details/42651949

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;
}

展开阅读全文

没有更多推荐了,返回首页