1:Qt信号和槽的优势和不足?
优势:
- 类型安全:信号的参数类型和参数个数和槽的参数类型和参数个数相同。不过,一个槽的参数个数可以少于信号的参数个数,但是缺少的参数必须是信号参数的最后一个或者最后几个。
- 灵活运用:信号和槽的机制增强了对象间通信的灵活性,一个信号可以关联多个槽,也可以多个信号关联一个槽。
- 松散耦合:激发信号的对象无需知道哪一个对象的槽进行相应,只需要在适当的时间发送信号就可以,也无需知道发出的信号是否被接收到。同样,对象的槽函数也无需知道哪一个信号关联了自己,qt保证适合的槽函数得到调用,即使关联对象在运行时被删除,应用程序也不会崩溃。
不足:
- 和回调函数相比,信号和槽的机制运行速度慢。通过传递一个信号调用槽函数比直接调用非虚函数运行速度慢十倍,原因如下:
- 需要定位接受信号的对象。
- 存在一个信号关联多个槽的情况,因此需要安全遍历所有的关联。
- 编组/解组 解析传递的参数
- 多线程的时候,信号可能需要需要排队等待
信号和槽的本质是:回调函数
回调函数的本质是:“你想让别人的代码执行你的代码,别人的代码你又不能动”这种情况下产生的。
信号和槽的注意事项:
- 发送者和接收者都必须是QObject的子类,Lambda表达式无需接受者的除外。
- 使用signals标记信号函数,这是一个函数生命,返回void无需实现。
- 槽函数是普通的成员函数,会受public,private,protected的影响。
- 使用emit调用信号在合适的时候发出信号。
- 使用QObject:connect()函数连接信号和槽。
- 任何成员函数,static函数,全局函数,Lambda都可以作为槽函数。
- 一个信号可以连接多个槽,这些槽函数会一个接一个被调用但是调用顺序不确定。
- 一个信号可以连接到另一个信号,第一个信号发出,第二个也被发出,信号-信号的形式和信号-槽的形式没什么区别。
- 多个信号连接一个槽,任意一个信号发出,槽就会被调用。
- 槽可以取消链接。当一个对象被delete后,自动取消连接到这个对象的槽。
2:Qt情况下,Tcp通信的整个流程?
- 服务端
- 首先创建监听的套接字(Socket)[socket看作两个程序在通讯连接中的一个端点,一个程序将一段信息写入socket,该Socket将这段信息发送到两一个socket中,使得这段信息能够传送到其他程序中]
- 给套接字设置监听。
- 如果有连接请求到来,监听的套接字会发出信号newConnected。
- 接受连接,通过nextPendingConnection()函数,返回一个QTcpSocket类型的套接字对象(用于通讯)
- 使用通讯的套接字对象通讯:发送数据-write 接收数据:readAll/read
- 客户端
- 创建用于通讯的套接字
- 连接服务器:connectToHost
- 连接成功后与服务器通讯:发送数据-write 接受数据-read/readAll
3:Qt情况下,UDP通信的整个流程?
udp通信的服务端和客户端关系是对等的,做的处理也是一样的。
- 创建套接字对象
- 如果需要接受数据必须绑定端口
- 发送数据:writeDatagram
- 接受数据:readDatagram
4:Qt下多线程使用方式?
方法一:
- 创建一个QThread类派生。
- 在子线程中重写run函数,将处理操作写入该函数中。
- 在主线程中创建子线程对象,启动子线程,调用start函数
方法2:
- 将业务处理抽象为一个业务类。在该类中创建一个业务处理函数(一般为槽的形式)
- 在主线程中创建一个QThread对象
- 在主线程中创建一个业务类对象
- 将业务类对象,移动到movetoThread子对象中
- 在主线程中启动子线程
- 通过信号槽的方式,执行业务类中的业务处理函数。
多线程注意事项
- 业务对象,构造的时候不能指定父对象
- 子线程不能处理UI窗口
- 子线程只能处理一些数据相关的操作,不能设计窗口
多线程的情况下,信号槽是如何执行的: 可以通过connect函数的第五个参数,connectType进行控制信号槽执行时所在的线程。 直接连接:信号和槽在同一个线程中。 队列连接:信号和槽不在同一个线程中,如果在同一个线程中使用队列连接则会造成死锁。 自动连接:多线程为为队列连接,单线程为直接连接。
Qt:多线程同步的几种实现方式:
- 互斥量:QMutex 提供是线程之间的访问顺序化,QMutex的目的是为了一个对象/数据结构/一段代码在同一段时间内只有一个线程可以访问。使用lock和unlock进行加锁和解锁,如果没有解锁,则会造成死锁,其他线程永远无法访问。所以为了简便使用引入:QMutexLocker,使用更方便。
QMutex只允许某个时刻有一个线程对共享资源进行访问。如果存在多个线程对共享资源进行读取,同时只有一个线程进行写访问。可以使用QReadWriteLocker,实现多线程读取资源,写线程会组测所有的读线程,读线程之间的运行不进行同步。