计算机
c base
c++ 基础 作用域及生命周期
c++ template
c++ 内存视角
c++ 函数指针
c++ 基础 基础语法
c++ 多线程
c++ 性能
c++ 类 基础
c++ 类 对象模型 类析构
c++ 类 设计模式
cmake
CMAKE环境搭建 windows
创建第一个cmakelists.txt
构建稍复杂的项目
动态链接库
EX1
EX1 START
EX1 ANSWER
EX2
EX2 START
EX2 ANSWER
EX3
EX3 START
EX3 ANSWER
变量
控制流程
函数和宏
查找和使用外部库
生成器表达式
qt 开发环境
qt c++
理解QObject 1
理解QObject 4
qt index
qt qml quick
qt ui
qt 多线程
数据结构 数组
PC问题监控及排查
PC程序性能优化
OS
TOOL
C++ STL
编程漫谈
C++实战-生产者 消费者流水线
C++实战 IO
本站点使用 MrDoc 构建
-
+
理解QObject 1
# 深入理解QT中的QObject类(一) 笔记 ## 目录 - [1. 引言与项目创建](#1-引言与项目创建) - [2. QObject 类的基本使用](#2-qobject-类的基本使用) - [3. 深入理解 Q_OBJECT 宏与文档](#3-深入理解-q_object-宏与文档) - [4. 对象名称 (objectName)](#4-对象名称-objectname) - [5. 父子关系与内存管理](#5-父子关系与内存管理) - [6. 信号阻塞与连接](#6-信号阻塞与连接) - [7. AI 总结](#7-ai-总结) --- ## 1. 引言与项目创建 [原片 @ 00:00](https://www.bilibili.com/video/BV1vh4y1r7sc?t=0) 视频开始,介绍本次主题是深入理解 QT 框架中最重要的类之一:`QCoreApplication` 和 `QObject`。虽然 `QCoreApplication` 是应用程序的核心,但 `QObject` 是所有 Qt 对象的基类,更为重要。 为了演示,创建一个名为 `myobject` 的控制台工程(Console Application)。 ## 2. QObject 类的基本使用 [原片 @ 01:30](https://www.bilibili.com/video/BV1vh4y1r7sc?t=90) ### 2.1 创建自定义类 在项目中添加一个新的 C++ Class,命名为 `MyObject`,其基类选择为 `QObject`。Qt Creator 会自动生成头文件 (`myobject.h`) 和源文件 (`myobject.cpp`)。 ### 2.2 构造函数与析构函数 - **构造函数**:生成的默认构造函数带有一个参数 `QObject *parent = nullptr`。这是 Qt 的标准写法,用于指定父对象。 - **代码修改**: - 在头文件中添加 `signals:` 部分(暂时留空)。 - 在源文件的构造函数中添加 `qDebug() << "new MyObject";` 用于打印日志。 - 在头文件中声明析构函数 `~MyObject()`,并在源文件中实现,打印 `qDebug() << "delete MyObject";`。 ### 2.3 栈上创建 vs 堆上创建 通过在 `main.cpp` 中实例化对象来观察生命周期: 1. **栈上创建 (Stack Allocation)**: ```cpp MyObject o; // 局部变量 ``` - **现象**:程序运行时,先打印 "new MyObject",随后立即打印 "delete MyObject"。 - **原理**:对象在栈(Stack)上创建,当离开作用域(函数返回)时,析构函数自动被调用,对象被销毁。 2. **堆上创建 (Heap Allocation)**: ```cpp MyObject *o = new MyObject; // 指针变量 ``` - **现象**:只打印 "new MyObject",没有打印 "delete MyObject"。 - **原理**:对象在堆(Heap)上分配内存。如果不手动调用 `delete`,析构函数不会执行,导致内存泄漏。必须显式调用 `delete o;` 才能触发析构。 ## 3. 深入理解 Q_OBJECT 宏与文档 [原片 @ 10:00](https://www.bilibili.com/video/BV1vh4y1r7sc?t=600) 通过查看帮助文档(Documentation),深入了解 `Q_OBJECT` 类的特性。 ### 3.1 核心地位 - `QObject` 是所有 Qt 对象的基类(Base Class / Superclass)。 - 它是 Qt 对象模型(Qt Object Model)的核心。 ### 3.2 核心机制:信号与槽 (Signals and Slots) - `QObject` 引入了强大的 **信号和槽** 机制,用于对象间的通信。 - 可以通过 `connect()` 连接信号和槽,也可以通过 `disconnect()` 断开连接。 - 这种机制避免了无限制的循环通知(例如 A->B->C->A),因为可以临时阻塞信号。 ### 3.3 对象树 (Object Tree) - `QObject` 将对象组织成树状结构。 - **父子关系**:当创建一个对象并指定另一个对象为 `parent` 时,新对象会自动添加到父对象的子对象列表中。 - **所有权**:父对象成为子对象的拥有者(Owner)。当父对象被删除时,它会自动递归删除所有子对象。 ### 3.4 其他重要功能 - **对象名称 (`objectName`)**:每个对象都有名字,可用于查找(`findChild`)。 - **元对象系统 (`Meta-Object`)**:支持运行时类型信息,可以通过 `inherits()` 判断继承关系,通过 `className()` 获取类名。 - **事件处理 (`Event Handling`)**:支持接收、过滤事件(`installEventFilter`)。 - **定时器支持**:提供基本的 `startTimer` 等支持。 - **国际化支持**:支持翻译。 ### 3.5 Q_OBJECT 宏的作用 - 必须在类的私有部分添加 `Q_OBJECT` 宏。 - **原因**:启用信号、槽、属性等功能需要运行 **MOC (Meta-Object Compiler)**。MOC 是一个预处理器,它会扫描头文件,识别带有 `Q_OBJECT` 的类,并生成额外的 C++ 代码(如元对象代码),以支持反射和信号槽机制。如果不加此宏,这些高级功能将无法工作。 ## 4. 对象名称 (objectName) [原片 @ 20:00](https://www.bilibili.com/video/BV1vh4y1r7sc?t=1200) - **属性**:`objectName` 是 `QString` 类型。 - **方法**: - `objectName()`: 获取对象名称。 - `setObjectName(const QString &name)`: 设置对象名称。 - **信号**:`objectNameChanged(const QString &objectName)`。当对象名称改变时发出。 - **注意**:这与 C++ 变量名不同,是对象运行时的标识符。 ## 5. 父子关系与内存管理 [原片 @ 23:00](https://www.bilibili.com/video/BV1vh4y1r7sc?t=1380) ### 5.1 构造函数参数 ```cpp MyObject(QObject *parent = nullptr); ``` - 如果传入非空指针作为 `parent`,当前对象将成为该 `parent` 的子对象。 - **示例**:对话框(Dialog)包含“确定”和“取消”按钮。可以将对话框设为这两个按钮的父对象。 ### 5.2 自动删除机制 (Automatic Deletion) - **规则**:父对象的析构函数会删除其所有的子对象。 - **代码验证**: 1. 创建 `o1`。 2. 创建 `o2`,父对象设为 `o1` (`new MyObject(o1)`). 3. 创建 `o3`,父对象设为 `o2` (`new MyObject(o2)`). 4. 执行 `delete o1;`。 - **结果**:控制台输出三次 "delete MyObject"。说明 `o1` 删除了自己,然后递归删除了 `o2`,`o2` 又删除了 `o3`。整棵树都被清理了。 ### 5.3 deleteLater() - **问题**:直接 `delete` 可能会在事件循环中导致问题(例如正在处理某个事件时删除对象)。 - **解决方案**:使用 `deleteLater()`。 - 它不会立即删除对象,而是向事件循环发送一个 `DeferredDelete` 事件。 - 当事件循环空闲时(或下一次迭代时),对象才会被真正删除。 - **注意**:如果没有运行事件循环(如简单的控制台程序没有 `exec()`),`deleteLater()` 可能不会立即生效,或者需要在主线程的事件循环结束后才处理。视频中展示了在有 `a.exec()` 的情况下,`deleteLater()` 能安全地让对象在后续被清理。 ## 6. 信号阻塞与连接 [原片 @ 34:00](https://www.bilibili.com/video/BV1vh4y1r7sc?t=2040) ### 6.1 blockSignals() - **功能**:暂时阻止对象发出信号。 - **用法**:`bool old = obj->blockSignals(true);` - **返回值**:返回之前的阻塞状态(true/false)。 - **场景**:如果在修改多个相关对象的状态时,希望中间过程不触发信号,可以使用此方法。 ### 6.2 信号与槽的连接 (Signals and Slots) - **基本概念**:当一个对象发出信号时,连接的槽函数会被自动调用。 - **语法**: ```cpp QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot())); // 或者新版语法(C++11 lambda 或函数指针) QObject::connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot); ``` - **示例逻辑**: 1. 创建 `o1`, `o2`, `o3`。 2. 将 `o1` 的 `objectNameChanged` 信号连接到 `o2` 的 `setObjectName` 槽。 3. 将 `o1` 的 `objectNameChanged` 信号连接到 `o3` 的 `setObjectName` 槽。 4. 当修改 `o1` 的名称时,`o2` 和 `o3` 的名称也会自动同步更新。 ## 7. AI 总结 本视频详细讲解了 Qt 核心类 `QObject` 的基础知识。主要内容包括: 1. **生命周期管理**:对比了栈上对象(自动销毁)和堆上对象(需手动 delete)的区别。 2. **Q_OBJECT 宏**:强调了其在启用信号槽、元对象系统中的必要性,以及 MOC 编译器的作用。 3. **对象树与父子关系**:解释了 `parent` 参数的含义,即父对象拥有子对象的生命周期,父销毁时子自动销毁。 4. **内存安全**:介绍了 `deleteLater()` 在事件循环环境下的安全删除机制。 5. **信号与槽初步**:通过 `objectName` 变化的例子,演示了如何使用 `connect` 实现对象间的数据同步,并简要提及了 `blockSignals` 用于临时阻断信号。
peipeo
2026年5月16日 17:05
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码