Qt信号和槽连接两次会发生什么?

56

如果同一个信号和槽被连接两次会发生什么?

这个机制是如何处理的?

3个回答

59
几周前,我们的一名实习生不小心将一个信号连接到了一个插槽多次。想法是,在一个条件下,您会将插槽连接到信号,而在另一个条件下,您会将其断开连接。当您更改模式时,您会进行适当的工作。
好吧,他忘记在适当的时候断开连接。因此,每次更改模式时,您都会有一个新的连接到插槽。
最终结果是?1个连接== 1个对插槽的调用。2个连接== 2个对插槽的调用。3个连接== 3个对插槽的调用,依此类推。这些调用“同时”发生(我知道实际上它们并没有,因为它们在同一个事件线程上,但我的意思是所有调用都按顺序处理)。
正如mtvec在他的评论中指出的那样(他应该得到荣誉,请不要为我的工作点赞),Qt::UniqueConnection将防止此问题。

72
请注意,您可以使用Qt::UniqueConnection来防止这种情况发生。 - mtvec
@工作:我会添加一个包含此内容的答案。我不知道Qt已经添加了这个功能。感谢您指出。 - Troubadour
@Troubadour:我不想劫持San Jacinto的回答 :-) 或许他可以把它加到他的回答中。 - mtvec
@工作:你没有劫持任何答案。当你评论时,没有人提到Qt::UniqueConnection - Troubadour
@Troubadour:没错,但问题是关于实际发生了什么,而不是如何防止它。 - mtvec
我想指出Qt :: UniqueConnection的链接不再可用。 - tisaconundrum

9

通常会出现问题。连接槽两次甚至多次是可以接受的,但当信号被触发时,您的槽将为每个连接调用,这可能不是您想要的。

请注意,拥有多个连接并不一定是错误的。它们(可能)具有完全有效的用途。它们非常罕见,我肯定无法想到任何时候我将其用作功能。我能想起来的所有情况中,多个连接都是错误而不是预期结果。


好的,moc文件中到底有什么?它难道没有处理编程错误这种情况的能力吗? - itapadar
@itapadar:我认为他们不会费心去防止这种情况,因为这可能_不是_一个错误。不久前,我编写了一些代码,在某些情况下实际上依赖于该功能。 - Troubadour
@itapadar:事实上回想起来,我根本没有将其用作功能。它只是一个错误,我不得不绕过它。 - Troubadour
一个有用的例子是一个定时器调用多个不相关的函数。你可以编写一个函数来调用这些多个不相关的函数,或者只需将定时器信号连接到它们中的每一个。 - Shahbaz

9

如其他人所说,该插槽将被执行多次。

以下是一些注意事项:

  • 以前,在可能已经存在连接的情况下,“仅连接一次”模式的方法是首先调用断开连接,然后再连接以强制进行一次连接。
  • 现在,自4.6版本以来,也有更优雅的Qt::UniqueConnection方式,详见http://doc.qt.io/qt-5/qt.html#ConnectionType-enum

1
我不确定这是否是更优雅的解决方案。通常代码应该对称,如果不对称,则是一个错误。我担心 Qt::UniqueConnection 可能会被用于修补不规范的非对称代码的次数比其他任何目的都要多。 - Troubadour
是的,可以说这两种“连接一次”的方法都不好。另一方面,如果您从其他地方获得一个对象,可能会多次获得相同的对象,并且您所需做的就是侦听某个信号(一次),那么我能想到的唯一方法就是保留您已经见过的对象的列表。 这也不好。 而且disconnect(),connect()有点脆弱,因为如果发生任何更改,就必须小心保持它们同步。所以我更喜欢UniqueConnection。实际上,我很少看到“连接一次”方法,所以似乎并不是一个大问题。 - Frank Osterfeld
+1 对于指向 Qt::UniqueConnection 的指针的指引(这是我之前不知道的) - Tim Ruddick

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