最近遇到一个需求,由于以前有个项目使用了qt来实现(无界面),但是本人不熟悉C++ 只熟悉C,目前的需求是为了减小编译时的压力决定将qt全部用标准库代替,在翻代码的时候遇到了信号和槽,发现其中有一段是
connect(this,SIGNAL(signal_DataChange(QStringList)),m_pTripServer,SIGNAL(signal_DataChange(QStringList)));
将两个信号做了连接。
问题1 两个信号连接之后起了什么作用?
问题2 假如是信号和槽函数做了连接,那槽函数肯定是要执行某个操作,但是现在变成了信号,请问这种情况会执行某个操作吗?
问题3 第一个signal_DataChange 是this中的一个函数,用于做触发来使用,不知道我理解的是不是正确,第二个signal_DataChange 是m_pTripServer中的一个函数吗?
问题4 如果是作为信号的传递,那信号传递到了什么地方?
希望能帮忙讲解一下connect 两个signal 和 普通connect signal和槽有什么区别,
下面附上部分代码
class TripServer : public QTcpServer
{
Q_OBJECT
public:
explicit TripServer(CPointNode *pPointNode_, int nCommonAddress, QObject *parent = 0);
void timerEvent(QTimerEvent *);
signals:
void signal_DataChange(QStringList strTagNameList);
public slots:
void Slot_ClientSocketDisconnected();
private:
void incomingConnection(int socketId);
private:
QList<ClientSocket *> m_ClientSocketList;
QMap<QString,ClientSocket *> m_ClientSocketMap;
public:
void Set_Enable_AO_DO_IPAddressList(bool isEnDO,QList<QString> *pDO_List,bool isEnAO,QList<QString> *pAO_List);
void Set_LinkLayeronfigInfo(_AAALinkLayerConfigInfo_New *pLinkLayeronfigInfo);
private:
CPointNode *m_pPointNode;
int m_nCommonAddress;
_AAALinkLayerConfigInfo_New *m_pLinkLayeronfigInfo;
};
class CStart : public QObject
{
Q_OBJECT
public:
explicit CStart(const QString strFileName, QObject *parent = 0);
void timerEvent(QTimerEvent *event);
static CStart *s_pStart;
signals:
void signal_read_tag(QString strTagName_);
void signal_DataChange(QStringList strNameList_);
public slots:
void Slot_acceptError(QAbstractSocket::SocketError nSocketError);
void InitPointMap(const QDomElement &DeviceListElement_);
void InsertPoint(const QDomElement &PointElem_, int nPointType, int nDeviceAddress);
DCTAG_API int slot_dc_tag_read ();
public:
TripServer *m_pTripServer;
QHostAddress m_hostAddress;
QDomElement m_EleMainPort;
CPointNode m_PointNode;
TAG_DATA *m_pTags;
void InitHostAddressList();
private:
QDomElement m_ChannelElem;///< Channel节点
int m_nCommonAddress; ///< 设备地址
};
bool CStart::SetInitTCP(const QDomElement &MainPort_)
{
m_pTripServer = new TripServer(&m_PointNode,m_nCommonAddress,this);
m_pTripServer->Set_Enable_AO_DO_IPAddressList(m_isEnable_DO_IP_Limit,&m_DO_IPAddress,m_isEnable_AO_IP_Limit,&m_AO_IPAddress);
m_pTripServer->Set_LinkLayeronfigInfo(&m_LinkLayeronfigInfo);
connect(this,SIGNAL(signal_DataChange(QStringList)),m_pTripServer,SIGNAL(signal_DataChange(QStringList)));
connect(m_pTripServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),this,SLOT(Slot_acceptError(QAbstractSocket::SocketError)));
return TcpServerListen(MainPort_);
}
我参考了网上的教程,用标准库仿写了一个基本的信号槽函数,但是不支持connect两个signal,由于本人不熟悉c++,希望能得到帮助来针对两个signal连接的情况进行修改,下面附上我的信号槽demo
```c++
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
//槽类
template<class TParam>
class SlotBase
{
private:
/* data */
public:
virtual void slotFunction(TParam param) = 0;
virtual ~SlotBase() = default;
};
template <class TRecver, class TParam>
class Slot : public SlotBase<TParam>
{
private:
TRecver* m_pRecver;//定义一个接收者的指针,在构造中对其初始化
void(TRecver::*m_func)(TParam param);//定义一个接收者类中的成员函数指针
public:
Slot( TRecver* pObj, void(TRecver::*func)(TParam) )
{
this->m_pRecver = pObj;
this->m_func = func;//使用类外的 接收者类的对象指针 与 接收者类中的成要换函数指针进行初始化。
}
void slotFunction(TParam param) override
{
(m_pRecver->*m_func)(param);//成员对象指针调用雷内的成员函数。
}
};
//信号类
template <class TParam>
class Signal
{
private:
vector<SlotBase<TParam>*> signal_vector;
public:
template<class TRecver>
void addSlot(TRecver* pObj, void (TRecver::*func)(TParam))
{
signal_vector.push_back(new Slot<TRecver, TParam>(pObj, func));
}
void operator()(TParam param)
{
for (SlotBase<TParam> * p : signal_vector )
{
p->slotFunction(param);
}
}
};
class Recver1
{
public:
void func1(int param)
{
cout << "这是Recver1中的方法,参数为:"<< param << endl;
}
};
class Recver2
{
public:
void func2(int param)
{
cout << "这是Recver2中的方法,参数为:"<< param << endl;
}
};
class SendObj
{
public:
Signal<int> valueChanged;
public:
void testSignal(int value)
{
valueChanged(value);
}
};
#define connect(sender, signal, recver, method) (sender)->signal.addSlot(recver, method)
int main()
{
Recver1 * r1 = new Recver1;
Recver2 * r2 = new Recver2;
SendObj * sd = new SendObj;
connect(sd, valueChanged, r1, &Recver1::func1);
connect(sd, valueChanged, r2, &Recver2::func2);
sd->testSignal(10000);
return 0 ;
}
```