emit,幕后的故事

来源:互联网 发布:17173剑灵数据库 编辑:程序博客网 时间:2024/04/28 08:11

emit,幕后的故事(qt技术)

 

    当我们写下一下emit signal代码的时候,与这个signal相连接的slot就会被调用,那么这个调用是如何发生的呢?让我们来逐一解开其中的谜团。

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


  1. class ZMytestObj : public QObject
  2. {
  3.     Q_OBJECT
  4. signals:
  5.     void sigMenuClicked();
  6.     void sigBtnClicked();
  7. };

复制代码 

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


  1. // SIGNAL 0
  2. void ZMytestObj::sigMenuClicked()
  3. {
  4.     QMetaObject::activate(this, &staticMetaObject, 0, 0);
  5. }
  6. // SIGNAL 1
  7. void ZMytestObj::sigBtnClicked()
  8. {
  9.     QMetaObject::activate(this, &staticMetaObject, 1, 0);
  10. }
复制代码

每一个signal都会被转换为一个与之相对应的成员函数。也就是说,当我们写下这样一行代码:
emit sigBtnClicked();
当程序运行到这里的时候,实际上就是调用了void ZMytestObj::sigBtnClicked() 这个函数。

 

大家注意比较这两个函数的函数体,
void ZMytestObj::sigMenuClicked()  

void ZMytestObj::sigBtnClicked(),
它们唯一的区别就是调用 QMetaObject::activate 函数时给出的参数不同,一个是0,一个是1,它们的含义是什么呢?它们表示是这个类中的第几个signal被发送出来了,回头再去看头文件就会发现它们就 是在这个类定义中,signal定义出现的顺序,这个参数可是非常重要的,它直接决定了进入这个函数体之后所发生的事情。

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

在每个一具体的链接记录中,还保存了这个链接的类型,是自动链接类型,还是队列链接类型,或者是阻塞链接类型,不同的类型处理方法还不一样的。这里,我们就只说一下直接调用的类型。

对于直接链接的类型,先找到接收这个signal的对象的指针,然后是处理这个signal的slot的index,已经是否有需要处理的参数,然后就使用这些信息去调用receiver的qt_metcall 方法。

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

====================================
声明:
《Inside Qt Series》专栏文章是Qt核心技术论坛(InsideQt.com)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
作者保留版权,未经作者同意,不得用于任何商业用途

《Inside Qt Series》专栏文章总索引:
http://www.insideqt.com/bbs/viewthread.php?tid=9
本文原始地址:
http://www.insideqt.com/bbs/viewthread.php?tid=55

原创粉丝点击