Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

本页目录

Qt 6 版本、构建与字符编码边界 ​

1. 固定最低版本 ​

“Qt 6”不是单一 API 集,6.2 LTS、6.5、6.8 等小版本能力不同。项目应在 CMake 和 CI 明确最低版本:

cmake
find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets)
qt_standard_project_setup()

qt_add_executable(cae_app
  main.cpp
  mainwindow.cpp
  mainwindow.ui
  resources.qrc)
target_link_libraries(cae_app PRIVATE Qt6::Core Qt6::Widgets)
1
2
3
4
5
6
7
8
9

不要根据开发机最新版文档使用 API,却让包声明支持更旧版本。qmake 在 Qt 6 仍可用,但 Qt 官方新项目主线是 target-based CMake。

2. MOC、UIC 与 RCC ​

text
Q_OBJECT header/source -> MOC -> moc_*.cpp -> C++ compiler
.ui                  -> UIC -> ui_*.h
.qrc                 -> RCC -> qrc_*.cpp / resource data
1
2
3

这些是构建期代码生成,不是运行时反射魔法。CMake AUTOMOC/AUTOUIC/AUTORCC 或 qt_add_executable 负责把生成步骤放入依赖图。移动 Q_OBJECT、新增 .ui 后出现 undefined vtable,先检查生成文件是否参与 target,而不是手工 include 随机 moc 文件。

3. 模块迁移 ​

  • QRegExp 迁移为 QRegularExpression;
  • QDesktopWidget 迁移到 QScreen;
  • QGLWidget 迁移到 QOpenGLWidget;
  • QTextCodec 在 Core5Compat,新代码评估 QStringConverter 系列;
  • 模块/类是否存在应按目标 Qt 小版本文档确认。

4. QString 的单位 ​

QString 在 Qt 5/6 中都按 UTF-16 code unit 语义存储。size() 不是 Unicode code point 数,更不是用户感知 grapheme cluster 数:

text
BMP 字符:常为 1 个 UTF-16 code unit
补充平面字符:surrogate pair,2 个 code unit
“字母+组合附加符”:多个 code point,可能 1 个用户感知字符
1
2
3

截断、光标、列宽和文件名限制必须明确按 byte/code unit/code point/grapheme 哪个单位。

5. QByteArray ​

QByteArray 是拥有的字节序列,不自动表示 UTF-8。编码边界显式转换:

cpp
const QByteArray utf8 = text.toUtf8();
const QString decoded = QString::fromUtf8(utf8);
1
2

系统本地 8-bit 编码和 UTF-8 不是同义词。网络/文件协议应固定编码并处理无效输入,不依赖机器 locale。

6. C 字符串边界 ​

QByteArray::constData() 提供终止符便利,但数据可含内嵌 \0。跨 C API 优先同时传 data + size;临时 toUtf8().constData() 指针在完整表达式后失效,不能保存。

7. 面试速答 ​

问:QString 是 UTF-8 吗?

不是,它使用 UTF-16 code unit 语义;与外部 UTF-8 通过显式转换。

问:Qt 6 是否删除 qmake?

没有完全删除,但新项目和现代包消费通常优先 CMake。

问:MOC 是编译器吗?

它是 Qt 元对象代码生成器,输出普通 C++ 再交给 C++ 编译器。

8. 自测答案 ​

QString::size()==1 能否证明是一个用户可见字符?不能,反方向也不成立;显示字素需要 Unicode segmentation。QByteArray 能否直接当 UTF-8?只有协议明确且内容验证后才行。

Qt 6 版本判断的正确层次 ​

text
compile-time headers version -> QT_VERSION / QT_VERSION_CHECK
runtime library version      -> qVersion()
feature/module availability  -> CMake target + feature macros
platform capability          -> runtime query
1
2
3
4

用编译期宏选择 API 只能证明头文件版本;部署时若加载不兼容 Qt DLL/SO,问题属于 ABI/装载。不要仅比较字符串版本决定功能。

QString、QByteArray 与 std::string ​

text
QString    Unicode text, conceptually UTF-16 code units in Qt 6 API model
QByteArray arbitrary bytes / often UTF-8 at explicit boundary
std::string bytes; encoding is application contract
1
2
3

转换必须写明编码:

cpp
QByteArray wire = text.toUtf8();
QString text = QString::fromUtf8(wire);
1
2

toLocal8Bit 依赖系统 locale,不适合稳定文件/网络协议。

Unicode 不是“一字符一个索引” ​

QString 的 size() 以代码单元计数,用户感知字符可能由代理对、组合标记和 grapheme cluster 组成:

text
user-perceived glyph
 -> one or more Unicode code points
 -> one or more UTF-16 code units
1
2
3

截断、光标和列宽应使用 Qt/Unicode 边界算法,不能按 mid(i,1) 假定一个可见字符。

隐式共享与 detach ​

许多 Qt 值类型使用 copy-on-write:

text
a and b -> shared data block
b modifies -> detach/copy -> independent block
1
2

复制常便宜但不是永远 O(1):写入会分离,跨线程同时修改不同副本虽各自 detach,仍要避免共享外部状态和 iterator/reference 在 detach 后失效。

Qt/STL 容器边界 ​

Qt 6 API 与 STL 互操作增强,但选择应看模块接口、隐式共享、iterator 规则和 ABI。不要在热路径反复 QVector <-> std::vector 整体复制;在边界统一一次,内部保持单一权威表示。

序列化版本 ​

QDataStream 的 stream version 与应用 schema version 是两件事:前者控制 Qt 类型编码兼容,后者控制业务字段演化。文件头应包含 magic、schema、字节序/feature flags 和长度上限。

连续追问与自测 ​

问:QString 是 UTF-8 吗? 答:不是;与 UTF-8 字节边界需显式 from/toUtf8。

问:隐式共享是否保证线程安全? 答:引用计数/分离的内部机制不等于同一逻辑对象的复合操作线程安全。

  1. qVersion 与 QT_VERSION 区别? 答:运行时库版本与编译时头版本。
  2. toLocal8Bit 为何不适合协议? 答:结果依赖机器 locale,不稳定可移植。
  3. QDataStream version 能否替代业务 schema? 答:不能,二者演化责任不同。

工程深化:把本篇知识落到项目里 ​

这一节不是为了凑篇幅,而是把《Qt 6 版本、构建与字符编码边界》从“知道概念”推进到“能在项目里稳定使用”。 阅读时可以把每个知识点都追问成四件事:它保护什么边界,失败时有什么现象,怎样最小复现,怎样写进团队流程。

text
concept -> boundary -> failure signal -> minimal proof -> project rule
1

工程切片 1:最小可复现样例 ​

**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。把问题压缩到一个可以提交给同事的目录,保留源码、构建命令、版本输出和预期现象。

**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 事件循环 -> QObject -> 模型数据 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 2:接口边界 ​

**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。写清调用方能依赖什么、不能依赖什么,并把隐式假设转换成命名函数、配置项或测试。

**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> QObject -> 模型数据 -> 线程边界 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 3:失败注入 ​

**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。故意制造一个常见错误,让日志、断言或测试先失败,再用修复后的证据说明规则生效。

**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 4:跨平台差异 ​

**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。至少比较 Windows、Linux 或不同编译器下的一个差异,记录差异属于标准、实现还是平台约定。

**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 5:性能观察 ​

**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用小规模和压力规模各跑一次,区分算法成本、同步成本、I/O 成本和工具链配置成本。

**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 6:生命周期 ​

**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。标出资源创建、转移、共享、停止和销毁的顺序,特别关注错误返回和提前退出路径。

**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 诊断工具 -> 事件循环 -> QObject -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 7:诊断证据 ​

**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。保留命令、日志、符号、栈、测试输出或截图,让结论可以被另一个环境重新验证。

**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 事件循环 -> QObject -> 模型数据 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 8:维护策略 ​

**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。把一次性经验沉淀到 README、CI、脚本、示例工程或检查表里,避免只存在个人记忆中。

**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> QObject -> 模型数据 -> 线程边界 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 9:版本演进 ​

**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。为未来变更预留兼容策略:版本号、特性位、弃用窗口、迁移脚本和回滚入口。

**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 10:最小消费者 ​

**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。从使用者角度写一个小程序或小工程,只依赖公开接口,验证安装包、头文件和运行时行为。

**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 11:边界复盘 ​

**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用一张表说明问题发生在源码、编译、链接、加载、运行、关闭或发布中的哪一层。

**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 12:反例训练 ​

**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。写出一个看似能工作但不可维护的方案,再说明它在规模、团队协作或发布时会怎样失败。

**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 诊断工具 -> 事件循环 -> QObject -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 13:最小可复现样例 ​

**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。把问题压缩到一个可以提交给同事的目录,保留源码、构建命令、版本输出和预期现象。

**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 事件循环 -> QObject -> 模型数据 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 14:接口边界 ​

**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。写清调用方能依赖什么、不能依赖什么,并把隐式假设转换成命名函数、配置项或测试。

**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> QObject -> 模型数据 -> 线程边界 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 15:失败注入 ​

**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。故意制造一个常见错误,让日志、断言或测试先失败,再用修复后的证据说明规则生效。

**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 16:跨平台差异 ​

**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。至少比较 Windows、Linux 或不同编译器下的一个差异,记录差异属于标准、实现还是平台约定。

**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 17:性能观察 ​

**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用小规模和压力规模各跑一次,区分算法成本、同步成本、I/O 成本和工具链配置成本。

**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 18:生命周期 ​

**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。标出资源创建、转移、共享、停止和销毁的顺序,特别关注错误返回和提前退出路径。

**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 诊断工具 -> 事件循环 -> QObject -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 19:诊断证据 ​

**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。保留命令、日志、符号、栈、测试输出或截图,让结论可以被另一个环境重新验证。

**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 事件循环 -> QObject -> 模型数据 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 20:维护策略 ​

**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。把一次性经验沉淀到 README、CI、脚本、示例工程或检查表里,避免只存在个人记忆中。

**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> QObject -> 模型数据 -> 线程边界 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 21:版本演进 ​

**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。为未来变更预留兼容策略:版本号、特性位、弃用窗口、迁移脚本和回滚入口。

**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 22:最小消费者 ​

**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。从使用者角度写一个小程序或小工程,只依赖公开接口,验证安装包、头文件和运行时行为。

**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 23:边界复盘 ​

**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用一张表说明问题发生在源码、编译、链接、加载、运行、关闭或发布中的哪一层。

**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 24:反例训练 ​

**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。写出一个看似能工作但不可维护的方案,再说明它在规模、团队协作或发布时会怎样失败。

**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 诊断工具 -> 事件循环 -> QObject -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

本篇收束 ​

掌握《Qt 6 版本、构建与字符编码边界》的标志,不是记住所有名词,而是能把 事件循环、QObject、模型数据、线程边界、资源生命周期、诊断工具 放进一条可验证的工程链路。 先用最小样例建立判断,再用测试和脚本固定判断,最后把失败证据留给未来的自己和团队。

最后更新于:

Pager
下一篇← C++ 编程 / C++ Programming

持续记录,持续成长

Copyright © Tidenflow