何时使用信号和槽,何时不使用

24
我们正在使用提供信号和槽机制的Qt,我认为这是非常方便的。然而,强大的功能也意味着极易滥用,因此需要谨慎使用。
有没有任何关于信号槽使用的最佳实践?在这方面,我很难找到一些通用的指导准则。以下是一些问题(我对其中的一些问题有明确的看法,但并非我团队中所有成员都同意):
- 使用信号来报告错误是否可以? - 是否可以假定信号将被处理? - 信号是否可用于启动操作?例如,signal displayInfoScreen() 必须由显示信息屏幕的槽处理。
欢迎分享任何其他关于何时应/不应使用信号的观点!
5个回答

14

信号和槽是强大的,因为它们可以解耦对象。就像之前回答的那样,您不能假定一个信号已经连接了一个槽。

基于信号/槽的设计的一个主要缺点是很容易失去实现逻辑的跟踪,因为一个对象的一个操作可能会触发任何其他连接到发射信号的对象的其他操作。这很容易产生不想要的副作用、递归调用等问题。


13

使用信号来报告错误是否可以?

可以,例如,参考QFtp,其中done信号携带状态信息。它不会携带实际的错误信息,只是表明发生了一个错误。

可以假设信号会得到处理吗?

不可以。发送者永远不能假设这一点,但是特定的应用程序可能依赖于它。例如,代表“文件 - 新建”的QAction需要被处理才能使应用程序工作,但是该QAction对象并不关心它是否被处理。

信号可以用于启动操作吗?例如,信号displayInfoScreen()必须由显示信息屏幕的槽处理。

同样可以,例如QAction对象。但是,如果您想重复使用组件,则必须小心以确保实际类不依赖于它。


你认为错误只有在处理是异步的情况下才可以接受吗?此答案提供了Qt中使用示例,已被接受。 - larsmoa
谢谢!另外,如果可以的话,请添加一个状态返回值或状态参数(例如QString::toInt函数)。 - e8johan

11

假设一个信号会被处理,这是否可行?

不可以。信号是一种“发射即忘”的事物。谁连接了信号以及它的处理方式都不应该由信号的发出者关心。


6

使用信号来报告错误是否可行?

可以,但通常应根据情况而定。如果错误可能异步发生,则使用信号指示是完全适当的。如果错误仅在客户端代码调用某个特定函数时发生,则错误应作为该函数的响应而非信号。但是,在这两种情况之间有许多情况可能需要根据具体情况进行处理。

此外,信号槽机制可以使跨线程通信更加容易(这可能被认为是异步情况),我会将其用于此目的(无论是否存在错误)。

假设信号将被处理是否可行?

信号(在哲学上)旨在指示已发生某事。正如其他人所指出的那样,假设信号将与一个槽匹配甚至只与一个其他槽匹配永远不是一个好主意。

信号是否可用于启动操作?例如,信号displayInfoScreen()必须由显示信息屏幕的槽处理。

信号可用于启动操作,但可能不是您想要的方式。信号表示已发生foo。如果监视您的类的代码决定在发生foo时应显示对话框,则使用信号启动了该操作。但是,发出信号的类通常不负责确保发生适当的操作,因为它不负责执行该操作。 (如果是,则应将其作为同一类的一部分,并且不需要信号。)


4
信号/槽(也称为事件)是消除对象之间耦合的好方法。
例如,不要让视图了解模型的工作方式,并在模型更改时“监听”它们。模型负责说出何时发生变化以及如何变化。
使用事件的问题在于当您根据客户需求设计事件时。例如,您不应该有一个信号displayInfoScreen,因为它假设某些使用此信号的对象。相反,它应该是infoChanged,并且InfoScreenDisplayer侦听这些信号以在屏幕上显示它。如果需要,您可以稍后添加InfoTweeterPoster,每当它们更改时就会将信息发布到Twitter。

6
你写的是a.k.a.事件,但这并不正确。Qt带有单独的事件基础设施。 - e8johan

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