qt八股文

什么是信号与槽机制?信号和槽的参数必须完全一致吗?

信号与槽都需要在类中声明,信号用signals关键字,槽函数在QT5中可以用public slot,也可以用普通函数或lambda表达式。连接信号与槽要使用QObject的connect函数,格式一般是connect发送者,signal信号,接收者,slot槽函数。当发送者发射信号时,连接的槽函数就会自动执行。而且一个信号可以连接多个槽,多个信号也可以连接同一个槽,还能进行信号与信号的连接

参数不要求完全一致,只要求信号的参数个数大于等于槽的参数,并且对应位置的参数类型必须兼容

信号与槽中的第五个参数有什么作用?

连接类型 含义 适用场景
Qt::AutoConnection(默认) 自动判断:1. 若发送者和接收者在同一线程 → 等价于 DirectConnection(同步);2. 若发送者和接收者在不同线程 → 等价于 QueuedConnection(异步)。 绝大多数场景(无需手动指定),Qt 自动适配线程。
Qt::DirectConnection(直接连接) 信号触发时,立即在发送信号的线程中执行槽函数(同步执行),槽函数和信号在同一调用栈中。⚠️ 注意:若接收者在其他线程,槽函数会 "跨线程" 执行(可能导致线程安全问题)。 需同步执行、发送 / 接收者同线程,或明确要在发送线程执行槽函数的场景。
Qt::QueuedConnection(队列连接) 信号触发后,将槽函数调用封装成事件放入接收者的事件循环队列,发送线程不阻塞,槽函数在接收者的线程中异步执行。✅ 线程安全:跨线程信号槽的标准用法。 发送者和接收者在不同线程(如主线程发信号给子线程,或子线程发信号给主线程更新 UI)。
Qt::BlockingQueuedConnection(阻塞队列连接) 类似 QueuedConnection,但发送线程会阻塞,直到接收者的事件循环执行完槽函数后才继续。⚠️ 禁止在 "接收者和发送者同线程" 时使用(会导致死锁)。 需等待槽函数执行完成、跨线程且发送线程可阻塞的场景(如子线程请求主线程处理数据,需等结果返回)。
Qt::UniqueConnection(唯一连接) 不是独立的连接类型,而是修饰符(可和上述 4 种组合,如 `Qt::QueuedConnection Qt::UniqueConnection`)。作用:确保同一信号 - 槽的连接只创建一次,避免重复 connect 导致槽函数多次执行。 防止重复连接(如多次调用 connect 绑定同一信号槽)。

什么是事件循环eventloop?

在qt中,QEventloop是事件循环的实现类。你可以创建它来启动一个局部的事件循环,比如在对话框弹出时,它会开启自己的事件循环,让对话框能独立处理用户交互,不阻塞整个应用,当调用exec()方法启动循环后,它会一直运行到调用quit()或exit(),期间不断处理事件队列里的事件

什么是事件机制?

QT的事件机制是一个很灵活的系统,事件可以来自于系统,如鼠标点击、键盘输入,也可以由应用程序或其他对象手动发送。事件从产生到处理有一套完整的流程,先由QApplication或QCoreApplication的notify方法分发,然后经过事件过滤器,最后到达目标对象,调用它的event方法来处理具体的事件类型

cpp 复制代码
事件对象 → QApplication::notify() → 目标对象的事件过滤器 → 目标对象的event()函数 → 具体事件处理函数  

当鼠标点击事件产生后,Qt会先创建一个QMouseEvent对象,然后通过QApplication::notify()函数来分发这个事件。在分发过程中,如果目标对象安装了事件过滤器,会先调用过滤器的eventFilter()函数。如果事件没有被过滤,就会调用目标对象的event()函数,这个函数会根据事件类型调用具体的事件处理函数,比如mousePressEvent()。

想要实现事件过滤有哪几种方式?

有两种常用方式,第一种是让一个对象通过InstallEventFilter方法,给目标对象安装过滤器,然后重写这个对象的eventFilter函数来处理事件。第二种是在目标对象内部重写event方法,在事件分发到具体处理函数前进行拦截

qt当中的线程有哪两种实现方式?两种方式的实现的底层原理有什么区别?

第一种是继承QThead类,重写它的run方法,在run方法中编写线程需要执行的代码,然后通过start方法启动线程。第二种是使用QObject结合QThread,先创建一个QObject的子类,将线程任务写到槽函数里,接着把这个QObject对象移动到一个QThread对象中,通过信号触发槽函数来执行任务。

继承QThread时,run方法是线程入口,默认run里调用exec()启动事件循环,若重写run里没调用exec,线程执行完run就结束。而QObject+QThread方式,QObject移动到线程后,其槽函数会在线程的事件循环中执行,依赖线程的事件循环来调度任务,底层是通过事件的驱动机制来实现的

QT中怎么进行内存管理?线程怎么进行内存回收?

qt中主要使用对象树机制管理内存。当创建一个QObject对象时,如果指定了父对象,这个子对象就会被添加到父对象的子对象列表中。当父对象销毁时,它会自动销毁所有子对象,这样能有效避免内存泄漏,比如Qwidget窗口作为父对象,它上面的按钮、输入框等子控件,会在窗口关闭时一同被销毁

如果这个线程是QThread子类且通过new创建,你可以给它指定父对象,让父对象在销毁时顺带回收它,不过更常用的是在线程的run函数执行完毕后,调用deletelater方法,它会在事件循环中安排线程对象的销毁。movetoThread创建的线程通常通过两种方式释放,一种是线程执行完毕,系统自动回收线程资源,另一种是调用线程的终止方法比如stop,但推荐通过标志位控制循环退出,确保资源正确释放

mvc是什么

mvc是一种软件架构模式,把系统分为模型、视图、控制器三部分。模型负责数据和业务逻辑,比如存储用户信息和计算,视图就是用户看到的界面,控制器是连接两者,接收用户输入,比如点击按钮,然后调用模型处理数据再让视图显示结果,这种分离让代码更易维护和扩展

QPointer设计的意义是什么

QPointer设计的核心意义是管理QObject子类对象的生命周期,避免野指针问题。它像一个智能指针,当指向的QObject对象被销毁时,QPointer会自动置为nullptr。这样在使用前检查是否为空,就能防止访问已销毁对象导致的崩溃。比如在多线程场景中,一个线程销毁了对象,另一个线程通过QPointer能安全判断对象是否存活。

QPointer 不自动释放内存 :它只是 "智能判空",不会像 std::unique_ptr 那样自动 delete 对象,内存仍需手动释放(或通过父对象的父子机制自动释放)。

QPointer 依赖 Qt 的 QObject 销毁机制:

  1. QPointer 会监听所指向 QObjectdestroyed() 信号;
  2. QObject 对象被 delete 或父对象销毁导致其被销毁时,QPointer 内部的指针会自动变为 nullptr
  3. 访问 QPointer 指向的对象前,只需判断是否为空,即可避免访问已销毁对象导致的崩溃。
相关推荐
Quz4 天前
QML Hello World 入门示例
qt
xcyxiner7 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner8 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner8 天前
DicomViewer (添加模型类)3
qt
xcyxiner9 天前
DicomViewer (目录调整) 2
qt
xcyxiner9 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00611 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术11 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园11 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob11 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio