Qt: 信号的返回值是有效的,为什么官方文档说这是不可能/禁止的?

9

Qt文档中指出,信号的返回值是不可能的:

信号由 moc 自动生成,不能在 .cpp 文件中实现。它们永远不能有返回类型(即使用 void)。

相关的 SO 问题:

  1. Qt 信号可以返回一个值吗?
  2. Qt:槽函数返回值的含义?

然而,通过我的尝试(Qt 4.8.1),我可以告诉您返回值确实有效:

  1. 如果信号/槽在同一线程中,则 ConnectionType 可能为 Qt::AutoConnection
  2. 对于位于不同线程中的信号/槽,我需要使用 Qt::BlockingQueuedConnection

因此,在我的代码中,我通过以下方式调用信号:

QString dp = emit WscAircrafts::signalAircraftsJsonArray();

信号 moc 返回一个 QString

QString _t0;
void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(&_t0)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
return _t0;

这里是槽函数,它会返回一个 QString。
case 4: { QString _r = _t->slotAircraftJsonArray();
  if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = _r; }  break;

所有这些似乎非常简单,那么为什么会与文档相矛盾?使用返回值会有什么问题?就像我说的,在我的代码中,这似乎是有效的。


3
如果信号连接到多个槽中会发生什么? - Martin Beckett
2
在另一个类似的问题答案中,它说:“似乎这是可能的。我能够发出信号,并从连接到信号的插槽接收值。但是,问题在于它只返回了多个连接插槽中的最后一个返回值。”这可能是他们不想宣传此功能的原因。 - Roman Saveljev
@RomanSaveljev - 它是否还需要阻塞,直到插槽完成? - Martin Beckett
当然,有些情况下这种方法行不通。但在大多数情况下,这取决于您如何设置连接。例如,使用Qt::SingleConnection就没有多个插槽的风险,而使用Qt::BlockingQueuedConnection一次只有一个返回值。根据文档,“永远不要有返回值”是与明智使用不同的。尽管可能会有副作用,但仍然有许多使用情况需要返回值非常有用。 - Horst Walter
2
即使可能,也不一定是理想的,因为它违反了命令查询分离原则。换句话说,返回值的信号可能会使读者难以理解和推理程序。大多数读者可能期望信号是一个命令。信号可以解耦,但返回值的信号解耦程度较低。 - bootchk
是的,这是正确的。但是我不需要通过设置Qt :: BlockingQueuedConnection来显式地进行耦合吗? - Horst Walter
1个回答

5
问题是返回类型在连接时不进行兼容性检查,因此将一个返回双精度值的槽连接到返回单精度值的信号,会导致栈空间(无恶意)分配给浮点数溢出。

但这也意味着,如果返回类型匹配并且一切都正确完成,使用它们将不会有问题。 - Horst Walter
1
@HorstWalter 是的,除非连接已排队(在这种情况下,延迟的插槽调用可能会覆盖已释放的内存,但我没有深入检查),或者一个信号连接到多个插槽(在这种情况下,您只会得到最后一个插槽的结果)。 - Marc Mutz - mmutz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接