C++ 观察者模式二-----成员函数作回调

下面说说一下成员函数作回调函数的使用,并使用了观察者模式

怎么说呢,推荐一篇博文,参考

dankyeC++回调机制实现 

选取里面的signal—slot(信号与槽)来说,QT实现了信号与槽的整套机制,有兴趣的朋友可以去查看下源码信息

任何对象的槽可以绑定到一个对象的信号上,一个信号可以拥有多个槽。

介绍下将要登场的一些成员: slot类,类似一个连接器,将receiver 绑定到 signal上去,这样 sender就可以发signal,signal就会执行响应的slot里面的方法,slot直接调用绑定到slot里面的reciver

一个简单的signal/slot实现

template <typename T, typename T1>
class slot
{
public:
	slot(T *pObj, void (T::*pMemberFunc)(T1))
	{
		m_pObj = pObj;
		m_pMemberFunc = pMemberFunc;
	}
	void Execute(T1 para)
	{
		(m_pObj->*m_pMemberFunc)(para);
	}
private:
	T * m_pObj;
	void (T::*m_pMemberFunc)(T1 para);
};
template<typename T, typename T1>
class signal
{
public:
	void bind(T* pObj, void (T::*pMemberFunc)(T1))
	{
		m_slots.push_back(new slot<T, T1>(pObj, pMemberFunc));
	}
	~signal()
	{
		vector<slot<T,T1> *>::iterator ite = m_slots.begin();
		while (ite != m_slots.end())
		{
			delete *ite;
			ite++;
		}
	}
	void operator()(T1 para)//重载操作符()
	{
		vector<slot<T,T1> *>::iterator ite = m_slots.begin();
		while (ite != m_slots.end()) {
			(*ite)->Execute(para);
			ite++;
		}
	}
private:
	vector<slot<T,T1> *>m_slots;
};

class receiver
{
public:
	void callback1(int a)
	{
		cout << "receiver1:" << a << endl;
	}
	void callback2(int a)
	{
		cout << "receiver2:" << a << endl;
	}
};

//构造sender类产生signal信号
class sender
{
public:
	sender(int value) :m_value(value) {}
	~sender() {}
	int get_value()
	{
		return m_value;
	}
	void set_value(int new_value)
	{
		if (new_value != m_value)
		{
			m_value = new_value;
			m_sig(new_value);
		}


	}
	signal<receiver, int> m_sig;
private:
	int m_value;
};

int main()
{
	receiver r;
	sender s(5);
	s.m_sig.bind(&r, &receiver::callback1);

	s.m_sig.bind(&r, &receiver::callback2);
	s.set_value(6);
	return 0;
}

简述:上面的对应关系很简单 将sender 发送signal信号 receiver 定义自己的callback 通过 slot将信号与 receiver对应起来。
因为成员函数在类外不可直接调用,必须使用对象来进行调用,所以引如了一个对象,来对回调函数进行调用。
首先将receiver 通过 slot 绑定到 signal上。然后sender发送一个signal ,执行调用。相当于信号触发,来执行signal里绑定的槽的方法。
总体的思路挺清晰的。
上面的参数模板T,T1 T代表receiver类,T1代表int类型参数,
问题:
  sender类在实例化signal的时候必须提供两个模板参数,可是调用方哪会事先就知道receiver接收方的类型 呢,而且从概念上讲,事件发送方与接收方只需遵循一个共同的接口函数接口就可以了,与类没什么关系,
上个程序要求在实例化时就得填充receiver的类型,  也就决定了receiver只能一对一,而不能一对多,于是作出改进,将signal的参数T去掉,将T类型的推导延迟到绑定(bind)时,signal没有参数T,slot也就不能有,
可是参数T总得找个地方落脚啊,怎么办?让slot包含slotbase成员,slotbase没有参数T的,但slotbase只定义接口,真正的实现放到slotimpl中,slotimpl就可以挂上参数了,boost中any,share_ptr就是用此手法,


#include <vector>
#include <iostream>
using namespace std;
/*

version:2.0
*/

#include <vector>
#include <iostream>
using namespace std;
template<typename T1>
class slotbase
{
public:
	virtual void Execute(T1 para) = 0;//定义虚函数 作接口用
};
template<typename T,typename T1>
class slotimpl :public slotbase<T1>
{
public:
	slotimpl(T* pObj, void (T::*pMemberFunc)(T1 para))
	{
		m_pObj = pObj;
		m_pMemberFunc = pMemberFunc;
	}
	virtual void Execute(T1 para)
	{
		(m_pObj->*m_pMemberFunc)(para);
	}
private:
	T* m_pObj;
	void (T::*m_pMemberFunc)(T1 para);
};


template <typename T1>
class slot
{
public:
	template<typename T>
	slot(T*Obj, void (T::*pMemberFunc)(T1 para))
	{
		m_Slotbase = new slotimpl<T, T1>(Obj, pMemberFunc);
	}
	~slot()
	{
		delete m_Slotbase;
	}
	void Execute(T1 para)
	{
		m_Slotbase->Execute(para);
	}
private:
	slotbase<T1> *m_Slotbase;


};

template <typename T1>
class signal
{
public:
	template <typename T>
	void bind(T* pObj, void(T::*pMemberFunc)(T1 para))
	{
		m_slots.push_back(new slot<T1>(pObj, pMemberFunc));
	}
	~signal()
	{
		vector<slot<T1>*>::iterator ite = m_slots.begin();
		for (; ite != m_slots.end(); ite++)
		{
			delete *ite;
		}
	}
	void operator()(T1 para)
	{
		vector<slot<T1>*>::iterator ite = m_slots.begin();
		//for (; ite != m_slots.end(); ite++)
		//{
		//	(*ite)->Execute(para);
		//}
		while (ite != m_slots.end())
		{
			(*ite)->Execute(para);
			ite++;
		}
	}

private:
	vector<slot<T1>*> m_slots;
};

#define CONNECT(sender,signal,receiver,slot)  sender.signal.bind(receiver,slot)

class receiver
{
public:
	void callback1(int a )
	{
		cout << "receiver1: " << a << endl;

	}

};
class receiver2
{
public:
	void callback2(int a)
	{
		cout << "receiver2: " << a << endl;
	}
};
class sender
{
public:
	sender() :m_value(0) {};
	int get_value()
	{
		return m_value;
	}

	void set_value(int new_value)
	{
		if (new_value != m_value)
		{
			m_value = new_value;
			m_valueChanged(m_value);
		}
	}
	signal<int>m_valueChanged;
private:
	int m_value;
};

int main()
{
	receiver r;
	receiver2 r2;
	sender s;
	CONNECT(s, m_valueChanged, &r, &receiver::callback1);
	CONNECT(s, m_valueChanged,&r2,&receiver2::callback2);

	s.set_value(1);
	return 0;
}

  

 


原文地址:https://www.cnblogs.com/lobsterIT/p/5606744.html