晒晒QT链接信号槽源码

晒晒QT链接信号槽源码

主旨:本文主要是为了还原QT链接信号槽的真相

开发环境
qt 4.5.2

这是在是一个入门级的小问题
如果草函数声明时没有像这样指明:
     public  slots:
并且槽函数没有声明为虚函数,则会产生链接失败,否则无法响应。为什么呢?先将各处看起来搞得混淆难懂的角落曝光再说。

Q_OBJECT展开
 1      public
 2     template  < typename T >  inline 
 3      void  qt_check_for_QOBJECT_macro( const  T  & _q_argument)  const  
 4      int i = qYouForgotTheQ_OBJECT_Macro(this&_q_argument); i = i; }  
 5      static   const  QMetaObject staticMetaObject;  virtual   const  QMetaObject  * metaObject()  const virtual   void   * qt_metacast( const   char   * ); 
 6      static  inline QString tr( const   char   * s,  const   char   * =   0
 7      return staticMetaObject.tr(s, c); }  
 8      static  inline QString trUtf8( const   char   * s,  const   char   * =   0
 9      return staticMetaObject.trUtf8(s, c); }  
10      static  inline QString tr( const   char   * s,  const   char   * c,  int  n) 
11      return staticMetaObject.tr(s, c, n); }  
12      static  inline QString trUtf8( const   char   * s,  const   char   * c,  int  n) 
13      return staticMetaObject.trUtf8(s, c, n); }  
14      virtual   int  qt_metacall(QMetaObject::Call,  int void   ** ); 
15     
16      private :
17

Ui::TestQtDlgClass展开

 1class Ui_TestQtDlgClass
 2{
 3public:
 4    QWidget *widget;
 5    QHBoxLayout *horizontalLayout;
 6    QPushButton *pushButton;
 7    QPushButton *pushButton_2;
 8    QPushButton *pushButton_3;
 9
10    void setupUi(QDialog *TestQtDlgClass)
11    {
12        if (TestQtDlgClass->objectName().isEmpty())
13            TestQtDlgClass->setObjectName(QString::fromUtf8("TestQtDlgClass"));
14        TestQtDlgClass->resize(600400);
15        widget = new QWidget(TestQtDlgClass);
16        widget->setObjectName(QString::fromUtf8("widget"));
17        widget->setGeometry(QRect(5010024527));
18        horizontalLayout = new QHBoxLayout(widget);
19        horizontalLayout->setSpacing(6);
20        horizontalLayout->setMargin(11);
21        horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
22        horizontalLayout->setContentsMargins(0000);
23        pushButton = new QPushButton(widget);
24        pushButton->setObjectName(QString::fromUtf8("pushButton"));
25
26        horizontalLayout->addWidget(pushButton);
27
28        pushButton_2 = new QPushButton(widget);
29        pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));
30
31        horizontalLayout->addWidget(pushButton_2);
32
33        pushButton_3 = new QPushButton(widget);
34        pushButton_3->setObjectName(QString::fromUtf8("pushButton_3"));
35
36        horizontalLayout->addWidget(pushButton_3);
37
38
39        retranslateUi(TestQtDlgClass);
40        QObject::connect(pushButton, qFlagLocation("2""clicked()" "\0""e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h"":""64"), TestQtDlgClass, qFlagLocation("1""button1()" "\0""e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h"":""64"));
41        QObject::connect(pushButton_2, qFlagLocation("2""clicked()" "\0""e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h"":""65"), TestQtDlgClass, qFlagLocation("1""button2()" "\0""e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h"":""65"));
42        QObject::connect(pushButton_3, qFlagLocation("2""clicked()" "\0""e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h"":""66"), TestQtDlgClass, qFlagLocation("1""button3()" "\0""e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h"":""66"));
43
44        QMetaObject::connectSlotsByName(TestQtDlgClass);
45    }
 
46
47    void retranslateUi(QDialog *TestQtDlgClass)
48    {
49        TestQtDlgClass->setWindowTitle(QApplication::translate("TestQtDlgClass""TestQtDlg"0, QApplication::UnicodeUTF8));
50        pushButton->setText(QApplication::translate("TestQtDlgClass""PushButton"0, QApplication::UnicodeUTF8));
51        pushButton_2->setText(QApplication::translate("TestQtDlgClass""PushButton"0, QApplication::UnicodeUTF8));
52        pushButton_3->setText(QApplication::translate("TestQtDlgClass""PushButton"0, QApplication::UnicodeUTF8));
53        (void)TestQtDlgClass;;
54    }
 
55
56}
;


这里进行信号槽链接:
        QObject::connect(pushButton, qFlagLocation( " 2 "" clicked() "   " \0 "" e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h "" : "" 64 " ), TestQtDlgClass, qFlagLocation( " 1 "" button1() "   " \0 "" e:\\DEVELOP\\TEST\\TestQtDlg\\GeneratedFiles\\ui_testqtdlg.h "" : "" 64 " ));


flagged_locations代码
 1 const   int  flagged_locations_count  =   2 ;
 2 static   const   char *  flagged_locations[flagged_locations_count]  =   {0} ;
 3
 4 const   char   * qFlagLocation( const   char   * method)
 5 {
 6    static int idx = 0;
 7    flagged_locations[idx] = method;
 8    idx = (idx+1% flagged_locations_count;
 9    return method;
10}

11


 QObject::connect原始文件
QObject::connect
  1/**//*!
  2    \threadsafe
  3
  4    Creates a connection of the given \a type from the \a signal in
  5    the \a sender object to the \a method in the \a receiver object.
  6    Returns true if the connection succeeds; otherwise returns false.
  7
  8    You must use the \c SIGNAL() and \c SLOT() macros when specifying
  9    the \a signal and the \a method, for example:
 10
 11    \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 22
 12
 13    This example ensures that the label always displays the current
 14    scroll bar value. Note that the signal and slots parameters must not
 15    contain any variable names, only the type. E.g. the following would
 16    not work and return false:
 17
 18    \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 23
 19
 20    A signal can also be connected to another signal:
 21
 22    \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 24
 23
 24    In this example, the \c MyWidget constructor relays a signal from
 25    a private member variable, and makes it available under a name
 26    that relates to \c MyWidget.
 27
 28    A signal can be connected to many slots and signals. Many signals
 29    can be connected to one slot.
 30
 31    If a signal is connected to several slots, the slots are activated
 32    in an arbitrary order when the signal is emitted.
 33
 34    The function returns true if it successfully connects the signal
 35    to the slot. It will return false if it cannot create the
 36    connection, for example, if QObject is unable to verify the
 37    existence of either \a signal or \a method, or if their signatures
 38    aren't compatible.
 39
 40    For every connection you make, a signal is emitted; two signals are emitted
 41    for duplicate connections. You can break all of these connections with a
 42    single disconnect() call.
 43
 44    The optional \a type parameter describes the type of connection
 45    to establish. In particular, it determines whether a particular
 46    signal is delivered to a slot immediately or queued for delivery
 47    at a later time. If the signal is queued, the parameters must be
 48    of types that are known to Qt's meta-object system, because Qt
 49    needs to copy the arguments to store them in an event behind the
 50    scenes. If you try to use a queued connection and get the error
 51    message
 52
 53    \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 25
 54
 55    call qRegisterMetaType() to register the data type before you
 56    establish the connection.
 57
 58    \sa disconnect(), sender(), qRegisterMetaType()
 59*/

 60
 61bool QObject::connect(const QObject *sender, const char *signal,
 62                      const QObject *receiver, const char *method,
 63                      Qt::ConnectionType type)
 64{
 65    {
 66        const void *cbdata[] = { sender, signal, receiver, method, &type };
 67        if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
 68            return true;
 69    }

 70
 71#ifndef QT_NO_DEBUG
 72    bool warnCompat = true;
 73#endif
 74    if (type == Qt::AutoCompatConnection) {
 75        type = Qt::AutoConnection;
 76#ifndef QT_NO_DEBUG
 77        warnCompat = false;
 78#endif
 79    }

 80
 81    if (sender == 0 || receiver == 0 || signal == 0 || method == 0{
 82        qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
 83                 sender ? sender->metaObject()->className() : "(null)",
 84                 (signal && *signal) ? signal+1 : "(null)",
 85                 receiver ? receiver->metaObject()->className() : "(null)",
 86                 (method && *method) ? method+1 : "(null)");
 87        return false;
 88    }

 89    QByteArray tmp_signal_name;
 90
 91    if (!check_signal_macro(sender, signal, "connect""bind"))
 92        return false;
 93    const QMetaObject *smeta = sender->metaObject();
 94    const char *signal_arg = signal;
 95    ++signal; //skip code
 96    int signal_index = smeta->indexOfSignal(signal);
 97    if (signal_index < 0{
 98        // check for normalized signatures
 99        tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
100        signal = tmp_signal_name.constData() + 1;
101
102        signal_index = smeta->indexOfSignal(signal);
103        if (signal_index < 0{
104            err_method_notfound(sender, signal_arg, "connect");
105            err_info_about_objects("connect", sender, receiver);
106            return false;
107        }

108    }

109
110    QByteArray tmp_method_name;
111    int membcode = extract_code(method);
112
113    if (!check_method_code(membcode, receiver, method, "connect"))
114        return false;
115    const char *method_arg = method;
116    ++method; // skip code
117
118    const QMetaObject *rmeta = receiver->metaObject();
119    int method_index = -1;
120    switch (membcode) {
121    case QSLOT_CODE:
122        method_index = rmeta->indexOfSlot(method);
123        break;
124    case QSIGNAL_CODE:
125        method_index = rmeta->indexOfSignal(method);
126        break;
127    }

128    if (method_index < 0{
129        // check for normalized methods
130        tmp_method_name = QMetaObject::normalizedSignature(method);
131        method = tmp_method_name.constData();
132        switch (membcode) {
133        case QSLOT_CODE:
134            method_index = rmeta->indexOfSlot(method);
135            break;
136        case QSIGNAL_CODE:
137            method_index = rmeta->indexOfSignal(method);
138            break;
139        }

140    }

141
142    if (method_index < 0{
143        err_method_notfound(receiver, method_arg, "connect");
144        err_info_about_objects("connect", sender, receiver);
145        return false;
146    }

147    if (!QMetaObject::checkConnectArgs(signal, method)) {
148        qWarning("QObject::connect: Incompatible sender/receiver arguments"
149                 "\n        %s::%s --> %s::%s",
150                 sender->metaObject()->className(), signal,
151                 receiver->metaObject()->className(), method);
152        return false;
153    }

154
155    int *types = 0;
156    if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
157            && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))
158        return false;
159
160#ifndef QT_NO_DEBUG
161    {
162        QMetaMethod smethod = smeta->method(signal_index);
163        QMetaMethod rmethod = rmeta->method(method_index);
164        if (warnCompat) {
165            if(smethod.attributes() & QMetaMethod::Compatibility) {
166                if (!(rmethod.attributes() & QMetaMethod::Compatibility))
167                    qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", smeta->className(), signal);
168            }
 else if(rmethod.attributes() & QMetaMethod::Compatibility && membcode != QSIGNAL_CODE) {
169                qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
170                         smeta->className(), signal, rmeta->className(), method);
171            }

172        }

173    }

174#endif
175    QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);
176    const_cast<QObject*>(sender)->connectNotify(signal - 1);
177    return true;
178}

179

你可能感兴趣的:(晒晒QT链接信号槽源码)