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

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

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ Qt是一种流行的GUI开发框架,它结合了C++语言的强大性能和Qt库的丰富功能。在Qt中,回调函数是一种常见的编程模式,用于实现事件处理和信号与槽机制回调函数是指在特定事件发生时被调用的函数。在Qt中,回调函数通常用于处理用户界面的事件,例如按钮点击、菜单选择等。当这些事件发生时,Qt会自动调用相应的回调函数来执行特定的操作。 在C++ Qt中,回调函数可以通过以下几种方式实现: 1. 普通函数指针:可以将一个普通的C++函数指针作为回调函数传递给Qt的信号与槽机制。当信号触发时,Qt会调用该函数指针所指向的函数。 2. 函数对象:可以使用C++中的函数对象(Functor)作为回调函数。函数对象是一个类对象,重载了函数调用运算符(),可以像函数一样被调用。在Qt中,可以将函数对象作为回调函数传递给信号与槽机制。 3. Lambda表达式:C++11引入了Lambda表达式,它可以方便地定义匿名函数。在Qt中,可以使用Lambda表达式作为回调函数,直接在信号与槽连接语句中定义并传递Lambda表达式。 下面是一个简单的示例,演示了如何在C++ Qt中使用回调函数: ```cpp #include <QApplication> #include <QPushButton> // 普通函数作为回调函数 void myFunction() { qDebug() << "Button clicked!"; } int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Click me!"); QObject::connect(&button, &QPushButton::clicked, myFunction); button.show(); return app.exec(); } ``` 在上面的示例中,我们创建了一个QPushButton按钮,并将其clicked信号与myFunction函数进行连接。当按钮被点击时,myFunction函数会被调用,并输出一条消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值