1.说一下你对 Qt 中的 connect 函数的了解(信号与槽)
1> 首先描述信号、槽的定义
信号(Signal),就是在特定情况下被发射的事件,有些Qt提供的默认控件带有若干支持的信号,比如说 PushButton 常用的 clicked() 信号,StackedWidget 常用的 currentChanged() 信号;
2> 槽(Slot)就是响应信号的函数。与一般的成员函数一样,可以被任一类的访问控制符修饰(public、private和protected),与一般函数不同之处在于,其可以与一个信号关联,当信号被发射时,关联的槽函数就会被自动执行。
2> 说一下 connect() 方法,其是 QObject 类的一个静态函数,其作用就是将信号与槽关联;
4> 信号与槽的使用方式
一个信号可以连接多个槽,槽函数的触发顺序按照建立的顺序依次执行;
多个信号也可以连接同一个槽
且一个信号也可以连接另一个信号,这种情况就是一个信号会触发另一个信号
5> 信号与槽的使用规则
严格来说,信号与槽的参数列表需要完全一致,至少信号的参数不能少于槽的参数;
并且要使用信号与槽,类中需加入宏 Q_OBJECT
1.1 刚刚有提到槽函数的访问控制,那么不同的访问控制符修饰的槽函数有什么区别吗?
private、protected 修饰的槽函数无法与其他类对象的信号绑定;
(这里可以提及一下C++里面的访问控制)
2.说说信号与槽的同步异步处理?(同步:槽函数处理完毕之后再执行下一步; 异步:信号发送过程不发生阻塞)
这里就需要提及 connect 的五种方式,
1> 第一种是 Qt::DirectConnection,直连方式,即以同步的方式执行槽函数:
SignalClass sig;SlotClass slot;QObject::connect(&sig, &SignalClass::sigSendSig, &slot, &SlotClass::slot_pub,Qt::QueuedConnection);qDebug() << QTime::currentTime() << "send sig";sig.sendSig();qDebug() << QTime::currentTime() << "send sig end";
输出打印如下:
send sig QTime(“16:53:06.595”) slot_pub <- slot_pub 开始执行 QTime(“16:53:09.596”) slot_pub end <- slot_pub 结束 send sig end <- 发送信号处阻塞完毕
即指定了 Qt::QueuedConnection属性,发送信号处会阻塞直到槽函数执行完毕;
2> 然后是 Qt::QueuedConnection属性
指定该属性,然后当信号发出后,会排队到队列中,等到接收对象所在线程的事件循环取得控制权时才能够取得该信号,调用响应的槽函数。
举例:
QObject::connect(&sig, &SignalClass::sigSendSig, &slot, &SlotClass::slot_pub,Qt::QueuedConnection);
与上面代码相同仅替换 Qt::QueuedConnection模式,输出打印如下:
QTime(“16:58:37.349”) send sig QTime(“16:58:37.352”) send sig end QTime(“16:58:37.355”) slot_pub QTime(“16:58:40.367”) slot_pub end
可以看到此时槽函数不再阻塞;
总结: 以同步的方式处理信号,指定属性为 Qt::DirectConnection,以异步的方式处理信号,指定属性为 Qt::QueuedConnection
3.除了刚刚提到的两种槽函数连接方式,还有了解过其他的连接方式吗?
1> BlockingQueuedConnection,
2> Qt::UniqueConnection
这是为了限制重复连接相同的信号与槽;
3> Qt::AutoConnection
即 Qt 的默认连接方式,如果信号的发出和接收该信号的对象是属同一个线程,那这个工作方式与直连相同;否则指定为队列方式;
4.对于跨线程处理信号槽是怎么看?
5.向未启动的线程发送信号,然后启动该线程,该线程会处理之前已发送的信号吗?
会处理,因为无论事件循环是否开启,信号发送后会直接进入槽函数所衣服的线程的事件队列,直到事件循环开启,对应的槽函数才会在线程中得到调用;
6. 相比于回调函数,信号与槽的优势?
信号和槽的机制类似于回调函数,但是回调函数机制有两个缺陷:
- 1> 不是类型安全的(type-safe),不能保证在调用回调函数时可以使用正确的参数;
- 2> 是强耦合的. 处理函数必须知道调用哪个回调函数
