信 和槽(Signals & Slots)用于对象之间的通信。信 和槽机制是Qt的核心特性,可能也是与其他框架所提供的特性最不同的部分。信 和槽是由Qt的元对象系统(The Meta-Object System)实现的。
产生背景
在GUI编程中,当我们更改一个小部件时,我们通常希望通知另一个小部件。更一般地说,我们希望任何类型的对象都能够彼此通信。
例如,如果用户单击关闭按钮,我们可能希望调用窗口的Close()函数。
其他工具包使用回调实现这种通信。回调是指向函数的指针,因此,如果希望某个处理函数通知你某个事件,则需要将一个指向另一个函数(回调)的指针传递给处理函数。然后处理函数在适当的时候调用回调。虽然使用这种方法的成功框架确实存在,但是回调可能不够直观,而且在确保回调参数的类型正确性方面可能会遇到问题。
信 与槽
在Qt中,我们有一种替代回调技术的方法:使用信 和槽。当特定事件发生时发出信 。Qt的widgets有许多预定义的信 ,但是我们总是可以子类化widgets来添加我们自己的信 。槽是响应特定信 而被调用的函数。Qt的窗口小部件有许多预定义的槽,但通常的做法是子类化窗口小部件并添加自己的槽,以便处理需要的信 。
信 和槽机制是类型安全的:信 的签名必须与接收槽的签名匹配。(事实上,槽的签名可能比它接收到的信 短,因为它可以忽略额外的参数。)由于签名是兼容的,编译器可以帮助我们在使用基于函数指针的语法时检测类型不匹配。基于字符串的信 和槽语法将在运行时检测类型不匹配。信 和槽是松散耦合的:发出信 的类既不知道也不关心哪个槽接收信 。Qt的信 和槽机制确保,如果你将信 连接到槽,该槽将在正确的时间与信 的参数一起被调用。信 和槽可以接受任意数量的任意类型的参数。它们是完全类型安全的。
继承自QObject的所有类都可以包含信 和槽。当对象改变它的一些状态时,就会发出信 。它不知道也不关心是否有谁正在接收它发出的信 。这是真正的信息封装,并确保对象可以作为软件组件使用。
槽可以用来接收信 ,但它们也是普通的成员函数。就像一个对象不知道是否有任何东西接收到它的信 一样,一个槽也不知道是否有任何信 连接到它。这确保了可以用Qt创建真正独立的组件。

你可以将任意多的信 连接到一个槽,一个信 可以连接到任意多的槽。甚至可以将一个信 直接连接到另一个信 。(这将在第一个信 发出时立即发出第二个信 。)
信 和槽一起构成了一个强大的组件编程机制。
信
当对象的内部状态以某种方式发生变化时,对象的客户端或所有者可能会对此感兴趣,就会发出信 。信 是公共访问函数,可以从任何地方发出,但是我们建议只从定义信 及其子类的类发出信 。
当一个信 被发出时,连接到它的槽通常会立即执行,就像一个普通的函数调用一样。当发生这种情况时,信 和槽机制完全独立于任何GUI事件循环。当所有槽返回后,emit语句后面的代码就会执行。在使用排队连接时,情况略有不同;在这种情况下,emit关键字后面的代码将立即继续执行,槽将在稍后执行。
如果几个槽连接到一个信 ,当信 发出时,槽将依次执行。(这个顺序无法保证。)
信 是由moc(元对象编译器)自动生成的,不能在.cpp文件中实现。它们永远不能有返回类型(即使用void)。
关于参数的注意事项:我们的经验表明,如果信 和槽不使用特殊类型,那么它们的可重用性更好。如果QScrollBar::valueChanged()使用一种特殊类型,例如假想的QScrollBar::Range,那么它只能连接到专为QScrollBar设计的槽。将不同的输入小部件连接在一起是不可能的。
槽
当连接到槽的信 发出时,就会调用槽。槽是普通的c++函数,可以正常调用。它们唯一的特点是可以将信 连接到它们身上。
因为槽是普通的成员函数,所以它们在直接调用时遵循普通的c++规则。但是,作为槽,任何组件都可以通过信 槽连接调用它们,无论其访问级别如何。这意味着从任意类的实例发出的信 可以导致在不相关类的实例中调用私有槽。
你还可以将槽定义为虚拟的,这在实践中非常有用。
与回调相比,信 和槽的速度稍微慢一些,因为它们提供了更大的灵活性,尽管实际应用的差异并不大。一般来说,通过发出信 来调用槽的速度比使用非虚拟函数直接调用的速度大约慢十倍。这是定位连接对象、安全遍历所有连接(即检查后续接收器在发射过程中没有被销毁)和并以通用方式编组任何参数所需的开销。虽然10倍差距听起来可能很多,但是它比任何新建操作或删除操作的开销要小得多。只要执行后台需要新建或删除字符串、向量或列表操作,信 和槽开销就只占整个函数调用开销的很小一部分。 信 和槽机制的简单性和灵活性非常值得这些开销,用户甚至不会注意到这些开销。
相关资源:微兆板式家具孔槽设计软件–支持数控五面钻、六面钻、PTP加工中心…
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!