> 文章列表 > qt源码--信号槽

qt源码--信号槽

qt源码--信号槽

本篇主要从Qt信号槽的连接、断开、调用、对象释放等方面展开;

1.信号建立连接过程

connect有多个重载函数,主要是为了方便使用者,比较常用的有2种方式:

a. QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);

b. QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));

 a方式对应的源码如下:

 

 

SIGNAL、SLOT对应的宏定义:

所以以上代码展开后为:QObject::connect(&timer, "2timeout()", &loop, "1quit()");

此函数除了此部分外,其他均是根据函数参数查找到信号、槽在sender、receiver的QMetaObject中的偏移量,特别需要注意的地方是链接参数使用Qt::QueuedConnection时,会检测参数对应的类型:

 queuedConnectionTypes函数源码如下:

 当时用自定义类型时,除了需要使用Q_DECLARE_METATYPE及qRegisterMetaType外,还需而外注意传参类型的完全匹配,即如果参数类型const Custom &时,qRegisterMetaType则对应为:qRegisterMetaType<const Custom &>(),主要原因是按照字符串进行匹配,否则会打印Cannot queue arguments of type ‘xxx’,Make sure ‘xxx’ is registered using qRegisterMetaType警告。

接下来主要看一下QMetaObjectPrivate::connect函数;

 其信号与槽主要是通过QObjectPrivate::Connection结构进行存储,其对应的源码如下:

 

 而外需要注意的是以上标记红色框的部分:

其信号和槽的连接过程对应3个链表:

1、QObjectConnectionListVector *connectionLists顺序列表管理每一个信号对应的Connection对象

2、Connection *nextConnectionList管理每一个信号对应的多个接收者,即一个信号可以绑定多个对象

3、Connection *senders和Connection *next,Connection prev用来管理每一个信号对应的多个发送对象,即一个类有多个对象,每个对象都有可能发送此信号

 基本上链表关系如上所示,其addConnection的过程就是建立3个链表之间的关系,如果连接类型是Qt::UniqueConnection,则指挥建立一次连接

 此函数剩余部分为构建Connection对象,并使用q指针,建立链表连接

 

 QObjectConnectionListVector对象会根据信号在对象中的绝对偏移量动态扩展其大小,即申请顺序链表;

每次建立连接过程,会检测下链表,确认是否需要清除接收对象为空的对象;

connectedsignals采用了简单算法记录其信号是否建立连接;

2.信号断开过程:

其主要是通过disconnectHelper函数来断开连接

其主要是将receiver指针更改为空指针,并修改senders链表;

3、调用过程