阅读Qt signal & slots documentation,似乎新风格连接失败的唯一原因是: “如果已经有一个重复(完全相同的信号到同一对象上完全相同的插槽),连接将失败,连接将返回false“当Qt-5将失败时,连接
这意味着连接在第一次已经成功,并且在使用Qt :: UniqueConnection时不允许多连接。
这是否意味着Qt-5风格的连接总会成功?是否有其他原因失败?
阅读Qt signal & slots documentation,似乎新风格连接失败的唯一原因是: “如果已经有一个重复(完全相同的信号到同一对象上完全相同的插槽),连接将失败,连接将返回false“当Qt-5将失败时,连接
这意味着连接在第一次已经成功,并且在使用Qt :: UniqueConnection时不允许多连接。
这是否意味着Qt-5风格的连接总会成功?是否有其他原因失败?
的新型connect
在运行时仍可能会失败各种它可能会失败原因:
sender
或receiver
一个空指针。显然这需要一个只能在运行时发生的检查。您为信号指定的PMF实际上不是一个信号。由于缺乏适当的C++反射功能,您在编译时所能做的就是检查信号是发送者类的非静态成员函数。
但是,这还不足以使其成为一个信号:它也需要位于类定义中的signals:
部分。当moc
看到你的类定义时,它将生成some metadata,其中包含该函数确实是信号的信息。因此,在运行时,传递到connect
的指针在表中查找,如果找不到指针(因为您没有传递信号),connect
本身将失败。
对前一点的检查实际上需要比较指向成员函数的指针。这是一个特别棘手的一个,因为它通常涉及不同的TU:
moc_class.cpp
文件)。在这个TU中有上述表格,其中包含指向信号的指针(这些指针只是普通的成员函数)。connect(sender, &Sender::signal, ...)
的TU,它生成在表中查找的指针。现在,这两个TU可能在同一个应用程序中,或者一个在一个库中,另一个在您的应用程序中,或者可能在两个库中等;你的平台ABI开始发挥作用。
理论上,做1时存储的指针与做2时产生的指针相同。在实践中,我们发现了这种情况没有发生的情况。这是我前段时间报告的bug report,其中ARM上较旧版本的GNU ld生成的代码未通过比较)。
对于Qt,这意味着禁用某些优化和/或将一些额外的标志传递到我们知道发生这种情况并破坏用户软件的地方。例如,从Qt 5.9开始,除了x86和x86-64之外,不支持GCC上的-Bsymbolic*
标志。
当然,这并不意味着我们已经找到并修复了全部可能的地方。新的编译器和更积极的优化可能会在未来再次触发此错误,使connect
返回false,即使所有事情都应该起作用。
不,它并不总是成功。该文档给出了一个示例here,其中connect
将返回false,因为该信号不应包含变量名称。
// WRONG
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
label, SLOT(setNum(int value)));
是如果任一发送者或接收者都无效对象(nullptr例如)
例
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();
// Will succeed
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
delete obj1;
obj1 = nullptr;
// Will fail even if it compiles
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
这不是Qt5式连接 –
你是对的。 Appologies。 – user2027202827