首先,我们看看connect()函数的源码:
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method,
Qt::ConnectionType type)
{
//此处省略合法性判断的代码段
//...
//end
QByteArray tmp_signal_name;
if (!check_signal_macro(sender, signal, "connect", "bind"))
return QMetaObject::Connection(0);
const QMetaObject *smeta = sender->metaObject();
const char *signal_arg = signal;
++signal; //skip code
QArgumentTypeArray signalTypes;
Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
//解析信号的参数类型和参数个数,保存在signalTypes变量中
QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
//end
//获取信号的相对偏移值,该函数根据信号名找到正确的QMetaObject对象
int signal_index = QMetaObjectPrivate::indexOfSignalRelative(
&smeta, signalName, signalTypes.size(), signalTypes.constData());
//end
if (signal_index < 0) {
// check for normalized signatures
tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
signal = tmp_signal_name.constData() + 1;
signalTypes.clear();
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
smeta = sender->metaObject();
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
&smeta, signalName, signalTypes.size(), signalTypes.constData());
}
if (signal_index < 0) {
err_method_notfound(sender, signal_arg, "connect");
err_info_about_objects("connect", sender, receiver);
return QMetaObject::Connection(0);
}
signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
//获取信号的绝对偏移值,该值会被作为key值,在信号发出时会根据信号的key值找到对应的value,也就是ConnectionList对象指针。
signal_index += QMetaObjectPrivate::signalOffset(smeta);
//end
//槽的参数类型和个数解析以及槽的偏移值计算
QByteArray tmp_method_name;
int membcode = extract_code(method);
if (!check_method_code(membcode, receiver, method, "connect"))
return QMetaObject::Connection(0);
const char *method_arg = method;
++method; // skip code
QArgumentTypeArray methodTypes;
QByteArray methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
const QMetaObject *rmeta = receiver->metaObject();
int method_index_relative = -1;
Q_ASSERT(QMetaObjectPrivate::get(rmeta)->revision >= 7);
switch (membcode) {
case QSLOT_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
break;
case QSIGNAL_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
break;
}
if (method_index_relative < 0) {
// check for normalized methods
tmp_method_name = QMetaObject::normalizedSignature(method);
method = tmp_method_name.constData();
methodTypes.clear();
methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);