技术博客003

来源:互联网 发布:8管脚单片机 编辑:程序博客网 时间:2024/06/08 05:54
从Qobject(QObject.h)源码中可以看到QObject::connect的定义是这样的:[cpp] view plain copystatic 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 copyconnect(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 copyconnect(sender,SIGNAL(signal()),receiver,SLOT(slot()));  实际上就是connect(sender,“2signal()”,receiver,“1slot())”;  搞明白了实际的参数就可以来看connect的真正实现过程了,在QObject.cpp文件中可以找到connect的实现代码。[cpp] view plain copybool 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;  }  

原创粉丝点击