BOOST 信号与槽,获取槽函数返回值,使用占位参数传递信号携带的参数

 

test1: 展示了, 1 信号与槽的基本使用,    2 要获取槽函数的返回值时的注意事项

#if 1

/*
  参考blog   https://www.cnblogs.com/jiayayao/p/6246161.html   

Qt异步的实现实际上是将信号push到一个队列中,然后由统一的线程来处理信号对应的槽函数而已。
Boost的信号/槽在信号被触发时,槽函数只能是同步执行,没有像Qt那样的异步接口。
当然也可以根据这个原理自己封装带异步的信号/槽机制,不过那样的话应该需要另外开启线程了。

*/
#include <iostream>
#include <boost/signals2.hpp>
#include <boost/bind.hpp>

using namespace std;
using namespace boost::signals2;

void slots1()
{
    cout<<"slots111111111 called"<<endl;
}
void slots2()
{
    cout<<"slots222222222 called"<<endl;
}
class A
{
public:
    static int staticMemberFunc(int param)
    {
        cout<<"A::staticMemberFunc called, param: "<<param<<endl;
        return 11+param;
    }
    int memberFunc(int param)
    {
        cout<<"A::memberFunc called, param: "<<param<<endl;
        return 6+param;
    }
};
int main()
{
    boost::signals2::signal<void()>   sig;
    boost::signals2::signal<int(int)> sig2;

    A a;

    // --------- sig() test -----------------
    connection c1 = sig.connect(&slots1);
    connection c2 = sig.connect(&slots2);
    cout<<"First call-------------------"<<endl;
    sig();

    if (c2.connected())
    {
        c2.disconnect();
    }
    cout<<"Second call-------------------"<<endl;
    sig();


    // -------- sig2() test ---------------
    connection c3 =sig2.connect(&A::staticMemberFunc);               // 绑定静态成员函数  -----这是 1 处

    connection c4 =sig2.connect(boost::bind(&A::memberFunc, &a, _1));// 绑定成员函数
    // bind 使用 ,参考BLOG : https://www.cnblogs.com/benxintuzi/p/4862129.html   

    cout << "------test1---------: " << endl; 
    sig2(44);

    cout << "------test2---------: " << endl; 
    cout << *sig2(44) << endl; // 只能返回最后被调用的插槽的返回值
    
    //cout << sig2(44) << endl;  编译报错  , 猜测是不是和连接参数是指针 有关系
    //    于是我们来进行test3  
    cout << "------test3 --------: " << endl; 
    boost::signals2::signal<int(int)> sig3;  
    connection c5 =sig3.connect(A::staticMemberFunc);               // 绑定静态成员函数   -----这是 2处
    sig3(55);
    cout << *sig3(55) << endl; // 只能返回最后被调用的插槽的返回值           //              -----这是 3处

    // 实测 1 2 处,加不加取地址,都无所谓。 但是3处一定要加*符号。这是要获取槽函数的返回值的注意事项。

    return 0;
}

#endif

 makefile:

.PHONY: DOIT

DOIT:
	mips-linux-gnu-g++ -I.  my_boost_test.cpp -L./lib  -lboost_thread -lboost_system -o boost_app  -lrt -lpthread
bind 使用 ,参考BLOG : https://www.cnblogs.com/benxintuzi/p/4862129.html   

 

test2:   展示了使用占位参数来填写槽函数的优势所在:这样能够传递信号携带的参数。


#include <iostream>
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
 
using namespace std;
using namespace boost;
 
template <typename signature>
class Signal{
 
public:
	
	typedef boost::signals2::signal<signature>  defSignal;      //typedef =>信号
   
   typedef typename defSignal::slot_type       defSlot;        //typedef => 槽
 
public:
	//连接槽函数
	boost::signals2::connection connectFun(const defSlot& slot);
 
	//重载为函数对象
	void operator()(typename defSignal::template arg<0>::type a0,  typename defSignal::template arg<1>::type a1);
 
private:
	defSignal mSignal;
};
 

//接收信号后响应的函数
class FunRecv1{
 
public:
	void action(int a, int b){
	  cout << "result add = " << a + b << endl;
	}
};
 
//接收信号后响应的函数
class FunRecv2{
 
public:
	void action(int a, int b){
	  cout << "result mutil = " << a * b << endl;
	}
};
 
// 定义
template <typename signature>
boost::signals2::connection  Signal<signature>::connectFun(const defSlot& slot){

	return mSignal.connect(slot);
}
 
template <typename signature>
void Signal<signature>::operator()(typename defSignal::template arg<0>::type a0,  typename defSignal::template arg<1>::type a1){

	mSignal(a0,a1);
}

int main(){
    
	Signal<void(int,int)> mysignal;
	FunRecv1 obj_fun1;
	FunRecv2 obj_fun2;
 
	//boost::function<void(int,int)> myfun = boost::bind(&FunRecv1::action,&obj_fun1,_1,_2);
	//信号连接槽函数
   #if  0
	boost::signals2::connection con1 = mysignal.connectFun(boost::bind(&FunRecv1::action, &obj_fun1, 100, 200));
	boost::signals2::connection con2 = mysignal.connectFun(boost::bind(&FunRecv2::action, &obj_fun2, 11,  22));

   // 小结: 
   // 这里的缺陷,这里没有使用占位参数,所以槽函数内(FunRecvX::action成员函数),每次取的实参都是(100、200)和 (11、22)这两组数据。  

   #else
                                                                                                // 使用占位参数
	boost::signals2::connection con1 = mysignal.connectFun(boost::bind(&FunRecv1::action, &obj_fun1, _1,  _2 ));
	boost::signals2::connection con2 = mysignal.connectFun(boost::bind(&FunRecv2::action, &obj_fun2, _1,  _2 ));

   
   #endif


	mysignal(100,200);
 
   cout << "--------111111111-------" << endl;
	mysignal(80,70);
   cout << "--------222222222-------" << endl;

	con2.disconnect();
	mysignal(100,200);

   cout << "--------33333333-------" << endl;
	mysignal(80,70);
 
   return 0;
}

makefile:

.PHONY: DOIT

DOIT:
	mips-linux-gnu-g++ -I.  my_boost_test.cpp -L./lib  -lboost_thread -lboost_system -o boost_app  -lrt -lpthread

 运行结果:

当前使用占位参数的场景:

# 
# ./boost_app 
result add = 300
result mutil = 20000
--------111111111-------
result add = 150
result mutil = 5600
--------222222222-------
result add = 300
--------33333333-------
result add = 150
# 

不使用占位参数时:

# ./boost_app 
result add = 300
result mutil = 242
--------111111111-------
result add = 300
result mutil = 242
--------222222222-------
result add = 300
--------33333333-------
result add = 300
# 

  

 

 一下看不懂没关系,代码复制过去,运行一遍,再看看,就消化了。

 

 

 PS:

还可以设置优先级:

 connect的第一个参数是设置槽函数的优先级,数字越大的槽函数的优先级越低,越靠后执行。所有的槽函数都会被执行,只有最后一个槽函数的返回值作为最终的返回值返回给信号。

 

 

 

 

 

 

.

posted @ 2020-09-24 21:54  一匹夫  阅读(834)  评论(0编辑  收藏  举报