Qt Inside信号和槽之connect

栏目: IT技术 · 发布时间: 4年前

内容简介:上次和大家分享的是Qt信号和槽的一些宏定义以及元对象编译器。这次和大家分享信号和槽的很多讲Qt信号和槽的文章都会讲到元对象编译器生成的代码,也就是以一、connect

上次和大家分享的是Qt信号和槽的一些宏定义以及元对象编译器。这次和大家分享信号和槽的 connect 函数到底连接了什么、还有元对象编译器都生成了什么代码。

很多讲Qt信号和槽的文章都会讲到元对象编译器生成的代码,也就是以 moc_ 为前缀的 .cpp 文件,本例子中是在编译后 Debug 目录的 moc_counter.cpp 文件。当时我看了好多遍,最后还是没有很好的理解,随后就顺着信号和槽的执行过程进行理解。

一、connect

使用信号和槽之前,必须使用connect将信号和槽连接起来,那么在内部究竟都做了些什么呢?

首先connect是一个重载函数,我们最常使用的则是四个参数的调用,即默认连接类型为 AutoConnection ,也就是下面这个样子:

QMetaObject::Connection connect(const QObject * sender, const char * signal,

const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection)

之前说过SIGNAL和 SLOT 关键字,也就是说上次例子中的连接其实是这个样子:

QObject::connect(&a, 2signal_valueChanged(int),

&b, 1slot_setValue(int));

OK,接下来看一个连接所需要的信息,下面是一个简化过的数据。 Qt 更高的版本中又对数据进行了抽象。

struct QObjectPrivate::Connection

{

QObject *sender;

QObject *receiver;

union {

StaticMetaCallFunction callFunction;

QtPrivate::QSlotObjectBase *slotObj;

};

// 单独连接的 ConnectionList 的 next 指针

Connection *nextConnectionList;

// senders 链表

Connection *next;

Connection **prev;

QAtomicPointer argumentTypes;

QAtomicInt ref_;

ushort method_offset;

ushort method_relative;

uint signal_index : 27; // 信号范围(参考 QObjectPrivate::signalIndex())

ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking

ushort isSlotObject : 1;

ushort ownArgumentTypes : 1;

Connection() : nextConnectionList(0), ref_(2), ownArgumentTypes(true) {

// ref_ 赋值为 2,以便内部列表使用,同时供 QMetaObject::Connection 使用

}

~Connection();

int method() const { return method_offset + method_relative; }

void ref() { ref_.ref(); }

void deref() {

if (!ref_.deref()) {

Q_ASSERT(!receiver);

delete this;

}

}

};

可以查一查C++中结构体与类的区别与联系。

简单对里面的部分数据进行说明,如果遇到元对象编译器生成的代码再做扩展说明。

首先一个连接里面会存储发送对象与接收对象;

callFunction 是接收端的私有静态函数 qt_static_metacall()Q_OBJECT 宏中定义,由元对象编译器实现】,这个接收端私有静态函数是可以根据相对序号 ( 索引 ) 调用元方法的。该方法通过对索引计算就可以访问到对应的槽函数了,以后有机会再做详解。

元对象编译器扩展部分:

相对序号(索引 ) 与元方法:

在每一个 QMetaObject 中,槽、信号以及其它该对象可调用的函数都会分配一个从 0 开始的索引。它们是有顺序的,信号在第一位,然后是槽,最后是其它函数。这个索引在内部被称为 相对索引。它们不包含父对象的索引。

Qt中常见的元方法就是信号和槽,其他不做扩展。

nextConnectionList 是下一个链表节点,由同样的 Connection 填充;

最终会构成如下的结构:

Qt Inside信号和槽之connect

一个对象可能有多个信号,Qt的 MedaObject 会把信号组装成一个 Signal Vector ,每个 signal 都可以根据序号 ( 索引 ) 来获得;每个信号都会维护一个要触发槽的链表,当一个 Signal 被调用时,对应链表内所有的槽都会被触发【以前看过当一个信号连接多个槽时,槽是被随机触发的,通过源码来看,一个信号对应的多个槽是按加入链表顺序来触发的,有机会做下验证】。

二、 小结

简单来说,一个connect就是存储了接口类 (QObject) 的一些信息,通过这些信息以及 Qt 的对象树模型再加上序号索引就可以快速找到一个信号所连接接口对象对应的槽函数。

这里面没和大家说字符串表以及内省表,有兴趣的话大家可以想一想这两个表在Qt元对象系统中究竟扮演了什么角色。

刚开始看这些信息可能会晕晕乎乎的,多看几遍,结合自己的疑问,很快就会理顺。

记录了自己成长的点点滴滴。

Qt Inside信号和槽之connect


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Namo Webeditor5.5一看就懂.

Namo Webeditor5.5一看就懂.

吳聲毅 / 金禾資訊 / 20040214 / NT$ 169

一看就懂系列書全以初學者的角度切入,全書以STEP BY STEP方式撰寫,並以豐富的圖片搭配教學,在最後更加上日常生活實例運用講解,一路學來一氣呵成。為了增進學習的效率更採用高級紙品全彩印刷,這麼好的書,您還在等什麼,一看就懂系列書保證是您最佳入門學習好伙伴。 本書特色: 1、一看就懂:Step by Step操作詳盡說明、讓您一看就懂 2、精選範例:精彩實務範例生動活......一起来看看 《Namo Webeditor5.5一看就懂.》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具