信号槽机制

  • 信号与槽是 QT 中用于对象间通信的机制。当一个对象的状态发生变化时,它会发出一个信号(signal);而另一个对象可以连接这个信号到一个槽(slot)函数上,当信号发出时,与之连接的槽函数会被自动调用。信号和槽都是普通的 C++ 函数,但信号只需声明,无需实现;槽函数则需要实现具体的逻辑。信号与槽机制是类型安全的,编译器会检查信号和槽的参数类型是否匹配。

  • 优点:类型安全,松散耦合。缺点:同回调函数相比,运行速度较慢。可用回调函数进行替代。当然槽函数也可以时虚函数。

  • 信号槽是同步的还是异步,主要取决于最后一个参数的设置,其中最常用的是前三种:

    Qt::AutoConnection(自动方式)Qt的默认连接方式,如果信号的发出和接收这个信号的对象同属一个线程,那个工作方式与直连方式相同;否则工作方式与排队方式相同。

    Qt::DirectConnection(直连方式)信号与槽函数关系类似于函数调用,同步执行,即当信号发出后,相应的槽函数将立即被调用。emit语句后的代码将在所有槽函数执行完毕后被执行。

    Qt::QueuedConnection(排队方式)此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信,异步执行,当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕。

    Qt::BlockingQueuedConnection(阻塞队列方式)要求信号和槽必须在不同的线程中,否则就产生死锁,这个是完全同步队列只有槽线程执行完成才会返回,否则发送线程也会一直等待,相当于是不同的线程可以同步起来执行。

    Qt::UniqueConnection(唯一链接)与默认工作方式相同,只是不能重复连接相同的信号和槽,因为如果重复连接就会导致一个信号发出,对应槽函数就会执行多次。

  • disconnect函数的使用场景,以及再次emit一个已经disconnect的信号会有什么问题:

    使用场景:希望信号再某些时间段不触发槽函数的情况、避免重复链接、接收对象需要被销毁时、改变信号链接关系时

    emit断开链接的信号,不会发生问题,QT内部会检查链接的列表。

    信号链接管理的最佳实践建议,不要频繁的断开信号链接,如需要临时断开,可使用QSignalBlocker类,且QT会再对象销毁时自动断开相关的链接。

  • 关于信号槽参数传递时候的拷贝问题,请参考这篇文章 数据是否发生拷贝?参数在信号-槽中的传递 - Larpx的站点|一个什么都记录的小站