关于Qt中信号和槽的Connection

来源:互联网 发布:好看的宫廷小说知乎 编辑:程序博客网 时间:2024/06/05 11:26

本文主要对我翻译的那篇博文中关于connection的建立过程做一些补充说明(那篇博文在这儿:http://blog.csdn.net/newthinker_wei/article/details/22785763)。


下面先看几个重要的成员变量和几个数据类型(类或结构体)的定义。

class Q_CORE_EXPORT QObjectPrivate : public QObjectData{    ...... ......    // QObjectPrivate中的几个结构体类型的定义:    struct Connection     {         QObject *sender;         QObject *receiver;         ...... ......        // The next pointer for the singly-linked ConnectionList         Connection *nextConnectionList;         //senders linked list         Connection *next;         Connection **prev;        ...... ......        ushort method_offset;         ushort method_relative;         uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())         ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking         ushort isSlotObject : 1;         ushort ownArgumentTypes : 1;            ......        int method() const { return method_offset + method_relative; }        ......    };    // ConnectionList is a singly-linked list     struct ConnectionList     {         ConnectionList() : first(0), last(0) {}         Connection *first;         Connection *last;     };    struct Sender     {         QObject *sender;         int signal;         int ref;     };    ...... ......    // QObjectPrivate中的几个重要成员变量的定义:    QObjectConnectionListVector *connectionLists;       // QObjectConnectionListVector的定义在下一段代码中给出。    // QObjectConnectionListVector是以QObjectPrivate::ConnectionList为基础类型的    // Vector容器。每一个ConnectionList有一个first和一个last指针。    /*        This vector contains the all connections from an object.        Each object may have one vector containing the lists of        connections for a given signal. The index in the vector correspond        to the signal index. The signal index is the one returned by        QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).        Negative index means connections to all signals.        This vector is protected by the object mutex (signalSlotMutexes())        Each Connection is also part of a 'senders' linked list. The mutex        of the receiver must be locked when touching the pointers of this        linked list.    */    Connection *senders;     // linked list of connections connected to this object     Sender *currentSender;   // object currently activating the object    ...... ......};


QObjectConnectionListVector的定义:

class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList> { public:     bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse     bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet     int inUse; //number of functions that are currently accessing this object or its connections     QObjectPrivate::ConnectionList allsignals;     QObjectConnectionListVector()         : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)     { }         QObjectPrivate::ConnectionList &operator[](int at)     {         if (at < 0)             return allsignals;         return QVector<QObjectPrivate::ConnectionList>::operator[](at);     } };

可见QObjectConnectionListVector是从QVector模板类继承而来。这里不再贴出QVector的定义,只给出QtAssistant中对QVector模板类的介绍

The QVector class is a templateclass that provides a dynamic array.

QVector<T> is one of Qt'sgeneric containerclasses. It stores its items in adjacent(相邻的)memory locations and provides fast index-based access.


看了上面几个定义,现在可以了解connect和disconnect的过程了。


每个QObject对象都有一个QObjectConnectionListVector结构,这是一个Vector容器,它里面的基本单元都是ConnectionList类型的数据,ConnectionList的个数与该QObject对象的signal个数相同。每个ConnectionList对应一个信号,它记录了连接到这个信号上的所有连接。前面已经看到ConnectionList的定义中有两个重要成员:first和last,他们都是Connection 类型的指针,分别指向连接到这个信号上的第一个和最后一个连接。所有连接到这个信号上的连接以单向链表的方式组织了起来,Connection结构体中的nextConnectionList成员就是用来指向这个链表中的下一个连接的。


同时,每个QObject对象还有一个senders成员,senders是一个Connection类型的指针,senders本身也是一个链表的头结点,这个链表中的所有结点都是连接到这个QObject对象上的某个槽的连接。不过这个链表跟上一段提到的链表可不是同一个!虽然他们可能有一些共同结点!下面详细说明。


每一个Connection对象都同时处于两个链表当中。其中一个是以Connection的nextConnectionList成员组织起来的单向链表,这个单项链表中每个结点的共同点是,他们都依赖于同一个QObject对象的同一个信号,这个链表的头结点就是这个信号对应的ConnectionList结构中的first;另一个链表是以Connection的next和prev成员组织起来的双向链表,这个双向链表中每个结点的共同点是,他们的槽都在同一个QObject对象上,这个链表的头结点就是这个Qobject对象的sender。这两个链表会有交叉(共同结点),但他们有不同的链接指针,所以不是同一个链表。


知道了这些,再来理解connect和disconnect就容易了。Connect的时候,就是先new一个Connection对象出来,设置好这个连接的信息后,将它分别添加到上面提到的两个链表中;disconnect的时候,就从从这两个链表中将它移除,然后delete掉。而当一个QObject对象被销毁的时候,它的sender指针指向的那个双向链表中的所有连接都会被逐个移除!


*******************************************************

讨论一下另一个不相关的问题:
写到这里正好附加一段说明。不知道有没有朋友注意到,我们在Qt开发过程中经常用到的connect函数,它的返回类型也是Connection。但是,那个Connection是QMetaObject命名域中的Connection类,而不是我们上面一直讨论的QObjectPravite命名域中的那个。那QMetaObject:: Connection类中包含哪些信息呢?它跟QObjectPravite::Connection又有何关系?


下面看QMetaObject::Connection的定义。可以看出,QMetaObject::Connection的第一个成员d_ptr就是一个QObjectPravite::Connection指针,所以QMetaObject::Connection已经包含了QObjectPravite::Connection类中的所有特性。


class Q_CORE_EXPORT QMetaObject::Connection {     void *d_ptr; //QObjectPrivate::Connection*     explicit Connection(void *data) : d_ptr(data) {  }     friend class QObject;     friend class QObjectPrivate;     friend struct QMetaObject; public:     ~Connection();     Connection();     Connection(const Connection &other);     Connection &operator=(const Connection &other); #ifdef Q_QDOC     operator bool() const; #else     typedef void *Connection::*RestrictedBool;     operator RestrictedBool() const { return d_ptr ? &Connection::d_ptr : 0; } #endif #ifdef Q_COMPILER_RVALUE_REFS     inline Connection(Connection &&o) : d_ptr(o.d_ptr) { o.d_ptr = 0; }     inline Connection &operator=(Connection &&other)     { qSwap(d_ptr, other.d_ptr); return *this; } #endif };





1 0
原创粉丝点击