QT一些细节内幕

本文深入探讨了QT中的信号与槽机制,包括emit信号的触发如何调用slot,MOC编译器如何处理信号与槽,以及connect函数的工作原理。通过分析源代码,揭示了SIGNAL和SLOT宏的转换过程,以及Qt对象的父/子关系在内存管理中的作用,防止内存泄漏。同时,讨论了在特定情况下可能导致问题的Qt对象删除顺序和内存管理陷阱。
摘要由CSDN通过智能技术生成

emit,幕后的故事

当我们写下一下emit signal代码的时候,与这个signal相连接的slot就会被调用,那么这个调用是如何发生的呢?

让我们来看一段例子代码:

class ZMytestObj : public QObject
{
Q_OBJECT
signals:
void sigMenuClicked();
void sigBtnClicked();
};

MOC编译器在做完预处理之后的代码如下:

// SIGNAL 0
void ZMytestObj::sigMenuClicked()
{
QMetaObject::activate(this, &staticMetaObject, 0, 0);
}
 
// SIGNAL 1
void ZMytestObj::sigBtnClicked()
{
QMetaObject::activate(this, &staticMetaObject, 1, 0);
}

每一个signal都会被转换为一个与之相对应的成员函数。也就是说,当我们写下这样一行代码:
emit sigBtnClicked();
当程序运行到这里的时候,实际上就是调用了void ZMytestObj::sigBtnClicked() 这个函数。大家注意比较这两个函数的函数体,
void ZMytestObj::sigMenuClicked()  void ZMytestObj::sigBtnClicked(),
它们唯一的区别就是调用 QMetaObject::activate 函数时给出的参数不同,一个是0,一个是1,它们的含义是什么呢?

它们表示是这个类中的第几个signal被发送出来了,回头再去看头文件就会发现它们就 是在这个类定义中,signal定义出现的顺序,这个参数可是非常重要的,它直接决定了进入这个函数体之后所发生的事情。

当执行流程进入到QMetaObject::activate函数中后,会先从connectionLists(这个变量根据传入的signal的index将每个signal对应的connectionList都包含进来)这个变量中取出与这个signal相对应的 connection list,它根据的就是刚才所传入进来的signal index。这个connectionlist中保存了所有和这个signal相链接的slot的信息,每一对connection(即:signal 和 slot 的连接)是这个list中的一项。

在每个一具体的链接记录(connectionList)中,还保存了这个链接的类型,是自动链接类型,还是队列链接类型,或者是阻塞链接类型,不同的类型处理方法还不一样的。这里,我们就只说一下直接调用的类型。
对于直接链接的类型,先通过connectionList找到接收这个signal的对象的指针,然后通过这个对象指针找到处理这个signal的slot的index(这个index表示是这个对象中slot的索引),已经是否有需要处理的参数,然后就使用这些信息去调用receiver的qt_metcall 方法。

在qt_metcall方法中就简单了,根据slot的index,一个大switch语句,调用相应的slot函数就OK了。
<

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值