用qt的知道,qt有方便簡單的信號槽機制,但需要專門的qt工具處理。
如果想直接使信號槽就可以使用sigslot庫,或者sigc++庫,或者boost中的signals,這裡介紹sigslot和sigc++庫。
sigslot.h:只有一個頭文件,使用簡單方便。
sigc++:包含文件多,但功能更強大。
http://sigslot.sourceforge.net/
#include "sigslot.h"改動:
//在sigslot.h的420,將: typedef sender_set::const_iterator const_iterator; //改為: typedef typename sender_set::const_iterator const_iterator;
class mySg { sigc::signal0<> sg1; // 無參數 sigc::signal2connectionsg2; // 2個參數 }
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
sig.sg1.disconnect(&slt); sig.sg1.disconnect_all();emiting
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; }
http://libsigc.sourceforge.net/
下載已經編好的庫文件,2.8.0版
注意1:在用高版本編譯時,如2.8.0,可能會提示找不到msvc_recommended_pragmas.h,可以在vs的
屬性 -> C/C -> 高級 -> 強制包含文件
去掉msvc_recommended_pragmas.h,或者添加一個msvc_recommended_pragmas.h文件,
注意2:在使用高版本(如2.9.7)編譯時,若提示找不到slot.cc等文件,可以使用低版本中的放入相應位置即可。
* 項目 -> 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;
}