一个很简陋的信号和槽的连接
#include<iostream>
#include<vector>
#include<string>
#include<Windows.h>
using std::vector;
using std::string;
//调试的时候用来看name,实际上没有用
class UObject
{
public:
UObject(){};
//template<class sender,class sig,class recver,class slot>
//void setsobj(sig signal,UObject* r,slot reactslot){};
string name;
};
template<class sender,class sig,class recver,class slot>
class connectstruct
{
public:
connectstruct(sender s,sig signal,recver r,slot reactslot)
{
m_s = s;
m_sig = signal;
m_r = r;
m_slot = reactslot;
}
sender m_s;
sig m_sig;
recver m_r;
slot m_slot;
};
//记录信号信息的类
template<class sig>
class ssinfor
{
public:
ssinfor(sig signal)
{
m_sig = signal;
m_count += 1;
m_c2 = m_count;
}
static int m_s; //发射次数
static sig m_sig;
static int m_count; //连接量
static int m_c2;
};
template<class sig>
int ssinfor<sig>::m_s = 0;
template<class sig>
sig ssinfor<sig>::m_sig = NULL;
template<class sig>
int ssinfor<sig>::m_count = 0;
template<class sig>
int ssinfor<sig>::m_c2 = 0;
static int i = 90;
template<class sender,class sig,class recver,class slot>
class sigfunc
{
public:
typedef vector<connectstruct<sender,sig,recver,slot> *> contype;
typedef vector<ssinfor<sig>* > calltype;
sigfunc(connectstruct<sender,sig,recver,slot>* connode)
{
funvec.push_back(connode);
ssinfor<sig> *s = new ssinfor<sig>(connode->m_sig);
callvec.push_back(s);
++i;
//std::cout<<((UObject*)connode->m_r)->name<<std::endl;
::SetTimer(NULL,i,1000,&sigfunc<sender,sig,recver,slot>::_timerproc);
//::Sleep(1000);
}
static contype funvec;
static calltype callvec;
static void CALLBACK _timerproc(
HWND hwnd,
UINT uMsg,
UINT idEvent,
DWORD dwTime
);
};
template<class sender,class sig,class recver,class slot>
vector<connectstruct<sender,sig,recver,slot> *> sigfunc<sender,sig,recver,slot>::funvec;
template<class sender,class sig,class recver,class slot>
vector<ssinfor<sig>* > sigfunc<sender,sig,recver,slot>::callvec;
template<class sender,class sig,class recver,class slot>
void CALLBACK sigfunc<sender,sig,recver,slot>::_timerproc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
{
//std::cout << L"Timer id :" << idEvent << std::endl;
if (ssinfor<sig>::m_s == 0)
{
ssinfor<sig>::m_c2 = 0;
}
else
{
//已修正错误
for (vector<connectstruct<sender,sig,recver,slot> *>::iterator i = funvec.begin(); i!= funvec.end(); ++i)
{
//std::cout<<((UObject*)(*i)->m_r)->name<<std::endl;
if(ssinfor<sig>::m_count != 0)
{
if ((*i)->m_sig == ssinfor<sig>::m_sig)
{
slot pfn = (*i)->m_slot;
((*((*i)->m_r)).*pfn)();
ssinfor<sig>::m_count -= 1;
if (ssinfor<sig>::m_count == 0)
{
ssinfor<sig>::m_s -= 1;
ssinfor<sig>::m_count = ssinfor<sig>::m_c2;
}
}
}
}
//ssinfor<sig>::m_s -= 1;
}
}
template<class sender,class sig,class recver,class slot>
void addsignode(connectstruct<sender,sig,recver,slot>* connode)
{
new sigfunc<sender,sig,recver,slot>(connode);
}
template<class sender,class sig,class recver,class slot>
void connect(sender s,sig signal,recver r,slot reactslot)
{
connectstruct<sender,sig,recver,slot> *connode = new connectstruct<sender,sig,recver,slot>(s,signal,r,reactslot);
addsignode<sender,sig,recver,slot>(connode);
}
template<class sig>
void callslot(sig)
{
ssinfor<sig>::m_s += 1;
}
class obj
{
public:
obj(){};
void sig1(){
std::cout<<"sig1 emited"<<std::endl;
callslot<void (obj::*)()>(&obj::sig1);//信号需要手工调用一次callslot函数
}
};
class listener : public UObject
{
public:
listener(){name = "LIS";}
void slot1(){
std::cout<<"listener worked"<<std::endl;
}
//string name;
};
class viewer: public UObject
{
public:
viewer(){name = "view";}
void show()
{
std::cout<<"view show worked"<<std::endl;
}
//string name;
};
class watcher: public UObject
{
public:
watcher(){name = "watch";}
void watch()
{
std::cout<<"watch worked!!"<<std::endl;
}
//string name;
};
int main()
{
obj *obj1 = new obj;
listener *lsner1 = new listener;
connect(obj1,&obj::sig1,lsner1,&listener::slot1);
//obj1->sig1();
viewer *viewer1 = new viewer;
connect(obj1,&obj::sig1,viewer1,&viewer::show);
//obj1->sig1();
watcher *watcher1 = new watcher;
connect(obj1,&obj::sig1,watcher1,&watcher::watch);
obj1->sig1();
obj1->sig1();
obj1->sig1();
MSG msg;
while (GetMessage(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
std::cin.get();
return 0;
}
运行结果
timer设置时间很短的时候槽被触发的顺序会不确定,原因还不清楚,可能是windows里面有对于timer的优化。