当Qt-5失败时,连接

时间:2017-04-19 06:12:16

标签: qt qt5

阅读Qt signal & slots documentation,似乎新样式连接失败的唯一原因是: "如果已经有重复(完全相同的信号到相同对象上完全相同的插槽),连接将失败并且connect将返回false"

这意味着第一次连接已成功,并且在使用Qt :: UniqueConnection时不允许多连接。

这是否意味着Qt-5风格的连接总会成功?还有其他原因导致失败吗?

3 个答案:

答案 0 :(得分:5)

由于各种原因,新式connect在运行时仍然会失败:

  • senderreceiver是空指针。显然,这需要进行只能在运行时进行的检查。
  • 您为信号指定的PMF实际上不是信号。缺乏正确的C ++反射功能,您在编译时可以做的就是检查信号是发送方类的非静态成员函数。

    但是,这还不足以使它成为一个信号:它还需要位于类定义的signals:部分。当moc看到您的类定义时,它将生成some metadata,其中包含该函数确实是信号的信息。因此,在运行时,传递给connect的指针会在表中查找,如果未找到指针,connect本身将失败(因为您没有传递信号)。

  • 对前一点的检查实际上需要对指向成员函数的指针进行比较。这是一个特别棘手的问题,因为它通常涉及不同的TU:

    1. 一个是包含moc生成的数据的TU(通常是moc_class.cpp文件)。在这个TU中,上面提到的表包含指向信号的指针(这些指针只是普通的成员函数)。
    2. 是您实际调用connect(sender, &Sender::signal, ...)的TU,它会生成在表中查找的指针。
    3. 现在,这两个TU可能在同一个应用程序中,或者可能是一个在库中,另一个在您的应用程序中,或者可能在两个库中等;你平台的ABI开始发挥作用。

      理论上,在执行1时存储的指针与执行2时生成的指针相同。在实践中,我们发现了不会发生这种情况的情况(参见我前段时间报告的这个bug report,其中旧版本的GNU ld on ARM生成的代码未通过比较)。

      对于Qt,这意味着禁用某些优化和/或将一些额外的标志传递给我们知道发生这种情况并破坏用户软件的地方。例如,从Qt 5.9开始,除了x86和x86-64之外,GCC上不支持-Bsymbolic*个标志。

      当然,这并不意味着我们找到并修复了所有可能的地方。新的编译器和更积极的优化可能在将来再次触发此错误,使connect返回false,即使一切都应该有效。

答案 1 :(得分:3)

是的,如果发送方或接收方都不是有效对象(例如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);

答案 2 :(得分:-2)

不,它并不总是成功。文档给出了一个示例here,其中connect将返回false,因为信号不应包含变量名。

// WRONG
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
             label, SLOT(setNum(int value)));