技术博客003

从Qobject(QObject.h)源码中可以看到QObject::connect的定义是这样的:
[cpp] view plain copy
static bool connect(const QObject *sender, const char *signal,  
                    const QObject *receiver, const char *member, Qt::ConnectionType =  
    #ifdef qdoc  
                        Qt::AutoConnection  
    #else  
        #ifdef QT3_SUPPORT  
                            Qt::AutoCompatConnection  
    #else  
                                Qt::AutoConnection  
        #endif  
    #endif  
    );  
inline bool connect(const QObject *sender, const char *signal,  
                    const char *member, Qt::ConnectionType type =  
    #ifdef qdoc  
                     Qt::AutoConnection  
    #else  
        #ifdef QT3_SUPPORT  
                                Qt::AutoCompatConnection  
        #else  
                                Qt::AutoConnection  
        #endif  
    #endif  
    ) const;  
其中第二个connect的实现其实只有一句话:
[cpp] view plain copy
{ return connect(asender, asignal, this, amember, atype); }  
所以对于connect函数的学习其实就是研究第一个connect函数。
我们在使用connect函数的时候一般是这样调用的:
[cpp] view plain copy
connect(sender,SIGNAL(signal()),receiver,SLOT(slot()));  
这里用到了两个宏:SIGNAL() 和SLOT();通过connect声明可以知道这两个宏最后倒是得到一个const char*类型。
在qobjectdefs.h中可以看到SIGNAL() 和SLOT()的宏定义:
[cpp] view plain copy
#ifndef QT_NO_DEBUG  
# define QLOCATION "\0"__FILE__":"QTOSTRING(__LINE__)  
# define METHOD(a)   qFlagLocation("0"#a QLOCATION)  
# define SLOT(a)     qFlagLocation("1"#a QLOCATION)  
# define SIGNAL(a)   qFlagLocation("2"#a QLOCATION)  
#else  
# define METHOD(a)   "0"#a  
# define SLOT(a)     "1"#a  
# define SIGNAL(a)   "2"#a  
#endif  
所以这两个宏的作用就是把函数名转换为字符串并且在前面加上标识符。
比如:SIGNAL(read())展开后就是"2read()";同理SLOT(read())展开后就是"1read()"。
[cpp] view plain copy
connect(sender,SIGNAL(signal()),receiver,SLOT(slot()));  
实际上就是connect(sender,“2signal()”,receiver,“1slot())”;  
搞明白了实际的参数就可以来看connect的真正实现过程了,在QObject.cpp文件中可以找到connect的实现代码。
[cpp] view plain copy
bool QObject::connect(const QObject *sender, const char *signal,  
                      const QObject *receiver, const char *method,  
                      Qt::ConnectionType type)  
{  
    {  
        const void *cbdata[] = { sender, signal, receiver, method, &type };  
        if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))  
            return true;  
    }  
  
    if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {  
        qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",  
                 sender ? sender->metaObject()->className() : "(null)",  
                 (signal && *signal) ? signal+1 : "(null)",  
                 receiver ? receiver->metaObject()->className() : "(null)",  
                 (method && *method) ? method+1 : "(null)");  
        return false;  
    }  
    QByteArray tmp_signal_name;  
  
    if (!check_signal_macro(sender, signal, "connect", "bind"))  
        return false;  
    const QMetaObject *smeta = sender->metaObject();  
    const char *signal_arg = signal;  
    ++signal; //skip code  
    int signal_index = smeta->indexOfSignal(signal);  
    if (signal_index < 0) {  
        // check for normalized signatures  
        tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);  
        signal = tmp_signal_name.constData() + 1;  
  
        signal_index = smeta->indexOfSignal(signal);  
        if (signal_index < 0) {  
            err_method_notfound(sender, signal_arg, "connect");  
            err_info_about_objects("connect", sender, receiver);  
            return false;  
        }  
    }  
  
    QByteArray tmp_method_name;  
    int membcode = extract_code(method);  
  
    if (!check_method_code(membcode, receiver, method, "connect"))  
        return false;  
    const char *method_arg = method;  
    ++method; // skip code  
  
    const QMetaObject *rmeta = receiver->metaObject();  
    int method_index = -1;  
    switch (membcode) {  
    case QSLOT_CODE:  
        method_index = rmeta->indexOfSlot(method);  
        break;  
    case QSIGNAL_CODE:  
        method_index = rmeta->indexOfSignal(method);  
        break;  
    }  
    if (method_index < 0) {  
        // check for normalized methods  
        tmp_method_name = QMetaObject::normalizedSignature(method);  
        method = tmp_method_name.constData();  
        switch (membcode) {  
        case QSLOT_CODE:  
            method_index = rmeta->indexOfSlot(method);  
            break;  
        case QSIGNAL_CODE:  
            method_index = rmeta->indexOfSignal(method);  
            break;  
        }  
    }  
  
    if (method_index < 0) {  
        err_method_notfound(receiver, method_arg, "connect");  
        err_info_about_objects("connect", sender, receiver);  
        return false;  
    }  
    if (!QMetaObject::checkConnectArgs(signal, method)) {  
        qWarning("QObject::connect: Incompatible sender/receiver arguments"  
                 "\n        %s::%s --> %s::%s",  
                 sender->metaObject()->className(), signal,  
                 receiver->metaObject()->className(), method);  
        return false;  
    }  
  
    int *types = 0;  
    if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)  
            && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))  
        return false;  
  
    QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);  
    const_cast<QObject*>(sender)->connectNotify(signal - 1);  
    return true;  
}  

猜你喜欢

转载自blog.csdn.net/sherryhaha123/article/details/72961685
003
今日推荐