用qt的知道,qt有方便简单的信号槽机制,但需要专门的qt工具处理。
如果想直接使信号槽就可以使用sigslot库,或者sigc 库,或者boost中的signals,这里介绍sigslot和sigc 库。
sigslot.h:只有一个头文件,使用简单方便。
sigc :包含文件多,但功能更强大。
信号槽库:sigslot.h和sigc 使用-尊龙凯时
官方地址
在vs2013中使用
包含头文件#include "sigslot.h"改动:
//在sigslot.h的420,将:
typedef sender_set::const_iterator const_iterator;
//改为:
typedef typename sender_set::const_iterator const_iterator;
基本使用:
signal0~signal8:信号类:作为类成员 class mysg
{
sigc::signal0<> sg1; // 无参数
sigc::signal2 sg2; // 2个参数
}
connection槽函数:作为类成员,类需要继承has_slots<>,且槽函数的返回值必须是void类型
class myslot: public : has_slots<>
{
public:
void on_func1(){} // 无参数,与信号对应
void on_func2(char*, double)(){} // 2个参数
};
mysg sig;
myslot slt;
sig.sg1.conncent(&slt,&myslot::on_func1);
sig.sg2.conncent(&slt,&myslot::on_func2);
disconnection解除连接:可以使用disconnect()和disconnect_all()
sig.sg1.disconnect(&slt);
sig.sg1.disconnect_all();
emiting发送信号:可以直接使用()运算符,也可以调用signal的emit函数
sig.sg1.emit();
sig.sg2("str",0.1);
实例:
#include
#include
#include
#include
using namespace std;
#include "sigslot.h"
using namespace sigslot;
#define pause_wait() {std::cout << "\nplease press any key to continue.\n";_getch();}
// class
enum objstate{normal = 0, hidden = 1};
class objectbase : public has_slots<>
{
public:
objectbase(){ px = 0; py = 0; state = normal; }
objectbase(const int &x, const int &y):px(x), py(y){ state = normal; }
~objectbase(){};
void onmoveby(const int &x, const int &y){px = x; py = y;}
void onresize(const int &x, const int &y){px = x; py = y;}
void onsetstate(objstate s){this->state = s;}
void onprintstate()
{
if(state == normal)
std::cout << "normal" << std::endl;
else if(state == hidden)
std::cout << "hidden" << std::endl;
else
std::cout << "error: error state value" << std::endl;
}
const int& getx(){return px;}
const int& gety(){return py;}
const char* getstate()
{
if(state == normal)
return "normal";
else if(state == hidden)
return "hidden";
else
return nullptr;
}
private:
objstate state;
int px;
int py;
};
class control
{
public:
signal2 moveby;
signal2 resize;
signal1 setstate;
signal0<> printstate;;
};
int main(int argc, char* argv[])
{
objectbase obj(10,10);
control ctrl;
#if(1)
ctrl.moveby.connect(&obj, &objectbase::onmoveby);
ctrl.resize.connect(&obj, &objectbase::onresize);
ctrl.setstate.connect(&obj, &objectbase::onsetstate);
ctrl.printstate.connect(&obj, &objectbase::onprintstate);
//ctrl.moveby.disconnect(&obj);
//ctrl.moveby.disconnect_all();
// start pro loop
pro_start:
while(true)
{
system("cls");
cout << "object information" << endl;
cout << "\t position_x: " << obj.getx() << endl;
cout << "\t position_y: " << obj.gety() << endl;
cout << "\t state: " << obj.getstate() << endl;
cout << "\n";
cout << "\t m: move object \n"
"\t r: resize object \n"
"\t s: set object state \n"
"\t p: print object state \n"
<< endl;
cout << "input:";
char ch = getchar();
switch(ch)
{
case 'm': // move
ctrl.moveby(10,10);
break;
case 'm':
ctrl.moveby.emit(-20,-20);
break;
case 'r':
case 'r': // resize
ctrl.resize.emit(0, 0);
break;
case 'p':
case 'p': // printstate
goto pro_printstate;
break;
case 's': // setstate
ctrl.setstate(normal);
break;
case 's':
ctrl.setstate.emit(hidden);
break;
case 'q':
case 'q': // exit
goto pro_exit;
break;
default:
break;
}
}
pro_printstate:
ctrl.printstate.emit();
pause_wait();
goto pro_start;
#endif
pause_wait();
pro_exit:
return 0;
}
官方地址
编译
下载已经编好的库文件,2.8.0版
注意1:在用高版本编译时,如2.8.0,可能会提示找不到ms_recommended_pragmas.h,可以在vs的
属性 -> c/c -> 高级 -> 强制包含文件
去掉msvc_recommended_pragmas.h,或者添加一个msvc_recommended_pragmas.h文件,
注意2:在使用高版本(如2.9.7)编译时,若提示找不到slot.cc等文件,可以使用低版本中的放入相应位置即可。
在vs中使用
* 项目 -> vc 目录 -> 包含目录: 添加 sigc 所在的目录 * 添加下列代码:
#include
#ifdef _debug
#pragma comment(lib,"sigcd.lib")
#else
#pragma comment(lib,"sigc.lib")
#endif
基本使用:
signal
信号类:可以作为其它类成员,也可直接定义
//返回值: int,2个参数:char*, double,参数个数可以直接指定
sigc::signal sg1;
sigc::signal2 sg2;
class mysg
{
sigc::signal2 sg3;
}
connection
连接槽函数,作为类成员时,要继承sigc::trackable;
ptr_fun, ptr_fun0~7 : 连接全局函数;
mem_fun, mem_fun0~7 : 连接类成员函数;
ptr_fun,mem_fun与signal之间只要参数类型对应就可连接, 并非一定要数字对应(如:ptr_fun3并非一定要与signal3对应连接)
sigc::connection ccsg1 = sg1.connect(sigc::ptr_fun(&func1));
class myslot: public : sigc::trackable
{
public:
int func2(char*, double)(){}
} obj;
sigc::connection ccsg2 = sg2.connect(sigc::mem_fun2(obj,&myslot::func));
class mysg: public : sigc::trackable
{
mysg(){auto cciter_sg3 = sg3.connect(sigc::mem_fun(*this,&mysg::on_func));}
sigc::signal2 sg3;
int on_func(char*, double)(){}
}
disconnection
如果不需要解连接,可以不用定义sigc::connection
ccsg1.disconnect();
ccsg2.disconnect();
emiting
// 发送信号:调用signal的emit函数
sg1.emit("str",0.1);
sg2.emit("str",0.1);
实例:
#include
#include
#include
#include
using namespace std;
#include
#ifdef _debug
#pragma comment(lib,"sigc280d.lib")
#else
#pragma comment(lib,"sigc280.lib")
#endif // _debug
#define pause_wait() {std::cout << "\nplease press any key to continue.\n";_getch();}
// class
enum objstate{normal = 0, hidden = 1};
class objectbase : public sigc::trackable
{
public:
objectbase(){ px = 0; py = 0; state = normal; setconnection(); }
objectbase(const int &x, const int &y) :px(x), py(y){ state = normal; setconnection(); }
~objectbase(){};
sigc::signal putmsg;
void onmoveby(const int &x, const int &y){px = x; py = y;}
void onresize(const int &x, const int &y){px = x; py = y;}
void onsetstate(objstate s){this->state = s;}
void onprintstate()
{
if(state == normal)
std::cout << "normal" << std::endl;
else if(state == hidden)
std::cout << "hidden" << std::endl;
else
std::cout << "error: error state value" << std::endl;
}
const int& getx(){return px;}
const int& gety(){return py;}
const char* getstate()
{
if(state == normal)
return "normal";
else if(state == hidden)
return "hidden";
else
return nullptr;
}
private:
objstate state;
int px;
int py;
void printmsg(const char* str){std::cout << str << std::endl; }
void setconnection()
{
putmsg.connect(sigc::mem_fun(*this, &objectbase::printmsg));
}
};
class control
{
public:
control(){}
sigc::signal moveby;
sigc::signal2 resize; // return void type, and 2 parameters
sigc::signal setstate;
private:
};
// print word steped by space
int printspacestr(const char* str)
{
int cnt = 0;
const char* p = str;
char ch;
std::cout << endl;
do
{
ch = *p;
cout << ch << ' ';
cnt ;
} while (* p != '\0');
std::cout << endl;
return cnt;
}
int main(int argc, char* argv[])
{
objectbase obj(0, 0);
control ctrl;
sigc::signal1 printss;
sigc::connection ccprintss = printss.connect(sigc::ptr_fun1(&printspacestr));
//ccprintss.disconnect();
sigc::signal0 printstate;
printstate.connect(sigc::mem_fun(obj, &objectbase::onprintstate));
ctrl.moveby.connect(sigc::mem_fun(obj, &objectbase::onmoveby));
ctrl.resize.connect(sigc::mem_fun(obj, &objectbase::onresize));
auto cciter_setstate = ctrl.setstate.connect(sigc::mem_fun(obj, &objectbase::onsetstate));
//cciter_setstate->disconnect();
// start pro loop
pro_start:
while(true)
{
system("cls");
obj.putmsg.emit("object information");
cout << "\t position_x: " << obj.getx() << endl;
cout << "\t position_y: " << obj.gety() << endl;
cout << "\t state: " << obj.getstate() << endl;
cout << "\n";
cout << "\t m: move object \n"
"\t r: resize object \n"
"\t s: set object state \n"
"\t p: print object state \n"
"\t a: print space word \n"
<< endl;
cout << "input:";
char ch = getchar();
switch(ch)
{
case 'm': // move
ctrl.moveby.emit(10,10);
break;
case 'm':
ctrl.moveby.emit(-20,-20);
break;
case 'r':
case 'r': // resize
ctrl.resize.emit(0, 0);
break;
case 'p':
case 'p': // printstate
goto pro_printstate;
break;
case 's': // setstate
ctrl.setstate.emit(normal);
break;
case 's':
ctrl.setstate.emit(hidden);
break;
case 'a':
case 'a':
goto rpo_printspacestr;
break;
case 'q':
case 'q': // exit
goto pro_exit;
break;
default:
break;
}
}
pro_printstate:
printstate.emit();
pause_wait();
goto pro_start;
rpo_printspacestr:
printss.emit("sigc_demo");
pause_wait();
goto pro_start;
pro_exit:
return 0;
}
射枪