Qt信 与槽机制原理及优缺点

信 和插槽用于对象之间的通信。信 和槽机制是Qt的核心特性,可能也是与其他框架提供的特性最大不同的部分。Qt的元对象系统使信 和插槽成为可能。

作为一个C/C++程序员来说 回调应该属于深入人心的机制了。其他工具包使用回调来实现这种通信。回调函数是一个指向函数的指针,所以如果你想要一个处理函数通知你一些事件,你可以将一个指向另一个函数(回调函数)的指针传递给处理函数。处理函数然后在适当的时候调用回调函数。但回调可能不太直观,而且在确保回调参数的类型正确性方面可能会遇到问题。

在Qt中,我们有一个回调技术的替代方案:我们使用信 和槽。当特定事件发生时发出信 。Qt的小部件有许多预定义的信 ,但是我们总是可以子类化小部件,添加一些自定义信 。槽(slots)是响应特定信 (signals)而调用的函数。Qt的小部件有许多预定义的槽,但是通常的做法是子类化控件并自定义槽函数,这样就可以处理感兴趣的信 。下图为信 与槽的关系图:支持一对多,多对一。

(1)信 和槽位机制是类型安全的:

信 的签名与接收的槽函数签名必须匹配。(事实上,槽函数的签名可能比它接收到的信 短,因为它可以忽略额外的参数。)由于签名是兼容的,所以当使用基于函数指针的语法时,编译器可以帮助我们检测类型是否匹配。基于字符串的信 和槽语法将在运行时检测类型不匹配。

(2)信 和插槽在软件层是解耦的:

发出信 的类既不知道也不关心哪个插槽接收信 。如果你将一个信 连接到槽函数,Qt的信 和插槽机制会确保立即调用携带信 传递过来的的参数的槽函数。信 和插槽可以接受任何类型的任意数量的参数,所以它们是完全类型安全的。

那什么是信 (signals)呢 p>

当object的内部状态以object的客户端或用户感兴趣的某种方式发生变化时比如点击、鼠标移动等,object就会发出信 。信 (signals)是公共访问函数,可以从任何地方发出,但最好只从该定义信 的类及其子类使用该信 。当信 发出时,通常采用直连方式连接槽函数,这种连接方式会立即执行槽函数,就像普通的函数调用一样。此时信 和槽机制完全独立于任何GUI事件循环。一旦所有的插槽都返回,emit语句之后的代码就会执行(同步发送)。当使用队列连接时,情况略有不同;在这种情况下,emit关键字后面的代码将立即继续,插槽将稍后执行(异步发送)。如果多个插槽连接到一个信 ,当信 发出时,插槽将按照它们连接的顺序依次执行。信 是由moc(元对象编译器)自动生成的,不能在.cpp文件中实现。它们永远不能有返回类型(即使用void)。

那什么是槽(slots)函数呢p>

slot是普通的c++函数,可以正常调用;它们唯一的特点是可以连接信 。因为槽函数是普通的成员函数,所以当直接调用时,它们遵循普通的c++规则。然而,作为Qt核心的机制槽函数,不管其访问级别,通过信 插槽连接,它们可以被任何组件调用。这意味着从任意类的实例发出的信 可能导致在不相关类的实例中调用私有插槽。与回调相比,信 和插槽稍微慢一些,因为它们提供了更大的灵活性,尽管实际应用程序中的差异并不大。一般来说,emit一个连接到一些插槽的信 ,大约比直接调用非虚函数慢十倍。原因是在定位连接对象、安全遍历所有连接(即检查在发送过程中后续槽函数是否被销毁)以及以通用方式编排任何参数所需的开销。虽然十个非虚函数调用可能听起来很多,但它的开销比任何new或delete操作都要小得多。一旦在后续执行需要new或delete的字符串、vector or list等操作,信 和槽开销只占整个函数调用开销的很小一部分。当你在槽中执行系统调用时,情况也是一样的;或间接调用十多个函数。信 和插槽机制的简单性和灵活性是非常值得的,用户甚至不会注意到这些开销。

注意,当与基于qt的应用程序一起编译时,定义了称为signals或slots的变量的第三方库可能会导致编译器警告和错误。要解决这个问题,#undef  + 错误的预处理器符

在需要信 发送方信息的情况下,Qt提供了QObject::sender()函数,它返回一个指向发送信 的对象的指针。用法如下:

refence to https://doc.qt.io/qt-5/signalsandslots.html

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年11月27日
下一篇 2020年11月27日

相关推荐