从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;
}
技术博客003
最新推荐文章于 2024-05-02 23:35:34 发布