signals2
概念
- 插槽可以是函数指针、函数对象、bind表达式、function对象。调用signals的成员函数connect()来将插槽连接到信号上,相当于为信号注册一个处理的handler。对signal对象调用()即为产生一个信号(signal提供了operator()),从而导致连接的所有插槽被调用。产生信号即调用signal的operator()的返回值是一个optional类型的对象,可以使用解引用操作符*来获得真正的返回值,而且默认情况下,这个返回值是最后被调用的插槽的返回值。signal会把参数传递给所有连接的插槽。
- 就像function一样,signal也是一个模板类,第一个模板参数是插槽函数类型签名,除了第一个模板参数外其他的模板参数都有缺省值,所以可以只传入第一个参数。
- signal::connect()的第一个参数为一个插槽,第二个参数为插入的位置,插入位置决定了插槽的调用顺序,默认值为at_back往后插入,at_front为往前插入,返回值是一个connection对象,可以这个对象来管理连接,如断开连接(disconnect)、测试连接(connected)等。
- 其它成员函数:
- num_slots()用来获得连接的插槽的个数,empty()用来判断连接的插槽数量是否为0。
- combiner()用来获取合并器,set_combiner()用来设置合并器,不过一般是在signal构造函数中直接设置合并器。
- disconnect()用来断开连接,disconnect_all_slots()用来断开所有连接的插槽,signal对象析构时会自动调用disconnect_all_slots()。
#include "boost/signals2.hpp"
int slots1(int n)
{
int iRet = n * n;
cout << "slot1 called, return value: " << iRet << endl;
return iRet;
}
int slots2(int n, int x)
{
int iRet = n * n * x;
cout << "slot2 called, return value: " << iRet << endl;
return iRet;
}
int slots3(int n)
{
int iRet = n * n;
cout << "slot3 called, return value: " << iRet << endl;
return iRet;
}
int slots4(int n)
{
int iRet = n * n;
cout << "slot4 called, return value: " << iRet << endl;
return iRet;
}
int main()
{
boost::signals2::signal<int(int)> sig;
//sig.connect(&slots1);
//sig.connect(&func,boost::signals2::at_front);
//sig.connect(1,&func_,boost::signals2::at_front); 组号
//sig.connect(&slots1);
boost::signals2::connection con1 = sig.connect(slots1);
boost::signals2::connection con2 = sig.connect(bind(slots2, _1, 100));
boost::signals2::connection con3 = sig.connect(slots3, boost::signals2::at_front);
boost::signals2::connection con4 = sig.connect(slots4);
bool b = con4.connected();
con4.disconnect();
b = con4.connected();
int iRet = *sig(1);
cout << "return value: " << iRet << endl;
return 0;
}
模板参数
-
前边我们说过,signal是一个模板类,它的第一个模板参数是插槽函数类型签名,其余模板参数都有缺省值。
-
①、signal<>的第二个模板参数
-
默认情况下,产生信号即调用signal对象的operator()的返回值是最后被调用的插槽的返回值,eg:
#include "boost/signals2.hpp"
template<int N>
class MySlots //模板函数对象类,可以用来生成一系列的插槽
{
public:
int operator()(int x)
{
cout << "slot" << N << " called" << endl;
return x * N;
}
};
int main()
{
boost::signals2::signal<int(int)> sig;
boost::signals2::connection con4 = sig.connect(MySlots<3>());
int iRet = *sig(10); //iRet为30
return 0;
}
-
signal<>的第三个模板参数
-
connect()时未被编组的插槽如果位置标志是at_front则在所有插槽调用之前调用,at_back为在所有插槽调用之后调用。
-
例如以下代码,插槽的调用顺序为:slots5, slots1, slots6, slots3, slots2, slots4
boost::signals2::signal<void(int)> sig;
boost::signals2::connection con1 = sig.connect(1, &slots1);
boost::signals2::connection con1 = sig.connect(1, &slots6);
boost::signals2::connection con2 = sig.connect(3, &slots2);
boost::signals2::connection con3 = sig.connect(2, &slots3);
boost::signals2::connection con4 = sig.connect(&slots4);
boost::signals2::connection con5 = sig.connect(&slots5, boost::signals2::at_front);
sig(100);