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,直连方式,即以同步的方式执行槽函数:

  1. SignalClass sig;
  2. SlotClass slot;
  3. QObject::connect(&sig, &SignalClass::sigSendSig, &slot, &SlotClass::slot_pub,
  4. Qt::QueuedConnection);
  5. qDebug() << QTime::currentTime() << "send sig";
  6. sig.sendSig();
  7. 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属性
指定该属性,然后当信号发出后,会排队到队列中,等到接收对象所在线程的事件循环取得控制权时才能够取得该信号,调用响应的槽函数。
举例:

  1. QObject::connect(&sig, &SignalClass::sigSendSig, &slot, &SlotClass::slot_pub,
  2. 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> 是强耦合的. 处理函数必须知道调用哪个回调函数