调用
是否有效QObject::connect(a, SIGNAL(somesig(someparam)), b, SLOT(someslot()));
没有参数?它似乎工作(没有抛出运行时异常),但我在文档中找不到引用。我发现只有someslot有一个默认参数才有可能。在这种情况下它是有效的。但是我的方法someslot没有与默认值相同的参数集(示例中没有参数)。
所以似乎可以将信号连接到参数较少的插槽?
答案 0 :(得分:14)
是的,没关系。在Signals & Slots文档中有一个简短的句子:
[...]信号的签名必须与接收槽的签名相匹配。 (事实上,一个插槽的签名可能比它收到的信号更短,因为它可以忽略额外的参数。)[...]
甚至还有一个例子就是在页面的下方解释默认参数。
答案 1 :(得分:1)
就标准C ++而言,Qt解决方案也可以解决。
通过调用方法来发出信号:
emit someSignal(3.14);
emit
关键字实际上解析为空#define
,因此上面的行只使用给定的参数调用方法someSignal
。该方法可能已在QObject
派生类中声明,如下所示:
class SomeObject: public QObject {
Q_OBJECT
public slots:
void firstSlot() { /* implementation */ }
void secondSlot(double) { /* implementation */ }
signals:
void someSignal(double); /* no implementation here */
};
这对您来说应该很熟悉,但您可能想知道信号的实际实现来自何处。正如您可能猜到的,这是Qt的元对象编译器(MOC)开始的地方。对于signals
部分中声明的每个方法,它在其生成的源中提供了实现大致看起来像这样:
void SomeObject::someSignal(double _t1)
{
void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
}
有趣的部分是void *_a[]
向量,其中填充了传递给信号的参数的指针。这里没什么特别的。
参数向量传递给QMetaObject::activate
,后者又进行一些线程安全检查和其他内务处理,然后开始调用已连接到信号的插槽(如果有的话)。由于信号到插槽的连接在运行时被解析(connect()
的工作方式),因此需要MOC的一点帮助。特别是,MOC还会生成一个qt_static_metacall()
实现您的类:
void SomeObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
SomeObject *_t = static_cast<SomeObject *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->firstSlot(); break;
case 1: _t->secondSlot((*reinterpret_cast< double(*)>(_a[1]))); break;
default: ;
}
} /* some more magic */
}
如您所见,此方法包含另一端将void *_a[]
向量从之前解析为函数调用。您还可以看到没有可变参数列表(使用省略号,...
)或其他可疑的诡计。
因此,要启发原始问题:何时,例如someSignal(double)
已连接到与信号签名匹配的secondSlot(double)
,调用将解析为case 1
中的qt_static_metacall
,并且只是按预期传递参数。
当信号连接到参数少于信号的firstSlot()
时,调用解析为case 0
并且firstSlot()
在没有参数的情况下被调用。传递给信号的参数在其void *_a[]
向量中保持不变。