每个「讲」知识点补齐核心概念 + 常见的坑,幻灯片与大纲同步

此前一版「讲」部分基本只是代码演示(贴代码 + 一句出处说明),没有讲透
知识点本身的原理。改为覆盖清单原则:每个知识点在大纲里至少固定两项——
核心概念(是什么/为什么,不只是怎么写)+ 常见的坑(注意事项/误区),
课堂实际讲解深度按学员反馈现场调整,但大纲必须列全,以免漏讲或退化成
纯代码演示。

- custom.css 新增 .concept-box/.pitfall-box 卡片样式
- day1–5.html 每个知识点前插入对应卡片,内容与 OUTLINE.md 的覆盖清单一一对应
This commit is contained in:
张宗平
2026-07-02 16:25:46 +08:00
parent ee902fb1e0
commit a6743fcea0
7 changed files with 716 additions and 31 deletions
+121
View File
@@ -40,6 +40,15 @@
- 如果后续需要这两项也做成可运行示例,请明确提出——这会涉及新增外部依赖,
需要单独确认。
**核心概念覆盖原则**(本轮追加):此前一版的"讲"部分基本只是代码演示(贴代码 + 一句出处
说明),没有讲透知识点本身的原理。本轮改为:**每个"讲"知识点在大纲里至少固定两项——核心
概念(是什么/为什么,不只是怎么写)+ 常见的坑(注意事项/误区)**,随知识点内联在下面各天
的表格后。这是**覆盖清单**而非固定讲稿:课堂实际讲解深度按学员反馈现场调整(PRETEST 摸底
好、进度快,可以点到为止;反馈吃力,可以就某个概念多展开几分钟),但大纲必须列全这些点,
以免讲课时漏掉、或降级回退到纯代码演示。幻灯片 `day1.html``day5.html` 每个知识点前都配了
对应的"核心概念/常见的坑"卡片(`custom.css` 里的 `.concept-box`/`.pitfall-box`),大纲里的
条目和幻灯片内容一一对应,改一处要同步改另一处。
## 1. 总体目标
1. 学员能说出 C++ 相对 C 的关键扩展机制在**哪个标准版本**成立/失效(复习向,
@@ -92,6 +101,15 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 敏捷 Scrum 项目开发管理 | 同上「服务流程图」里的迭代环节(需求分析→需求评审→项目研发→阶段评审→项目测试) |
| C++ 在企业中的应用 | 口头介绍,结合往届案例(如有) |
**核心概念与常见误区**
- **实习实训服务流程**:概念——需求分析→需求评审→项目研发/代码实现→阶段评审→项目测试/交付,
每环节都有明确"评审"节点把关;误区——把需求分析当走过场,跳过评审直接编码,后期返工成本
远高于前期对齐需求的成本。
- **四平台一标准**:概念——JIRA/Git/Wiki/OASIS 四个工具分别对应"谁在做什么/代码怎么变化/
知识怎么沉淀/进度怎么被看到"四个维度,缺一个都有协作盲区;误区——只用 Git 不用 Jira,代码
有版本历史但任务分工和进度没有可见记录。
**讨论(95min,分组,非编码)**
- **任务卡 1**
@@ -117,6 +135,25 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| CMake 项目构建 | 本仓库 `CMakeLists.txt``p03/CMakeLists.txt` | 用真实项目当教材:`option(BUILD_QT_PART)``add_subdirectory`、每个示例一个 `add_executable` 目标 |
| Vcpkg 包管理器(概念,无演示) | 无仓库代码 | C++ 生态的包管理器,解决"第三方库怎么装、怎么被 CMake 找到"的问题;本仓库用的是"隔离 Qt 手动装"而非 vcpkg,两种思路都要认识 |
**核心概念与常见的坑**(每个知识点至少覆盖这两项,课堂讲解深度按学员反馈调整;对应幻灯片
`day1.html` 每个知识点前的"核心概念/常见的坑"卡片):
- **namespace 作用域**:概念——作用域可跨文件延续、跨块合并,不是"文件顺序";坑——头文件里
`using namespace std;` 会把命名空间污染带给所有 include 它的地方。
- **函数重载决议**:概念——编译器靠名字改写(name mangling)区分重载,二义性源于"同样好"的
候选而非代码写错;坑——隐式类型转换会扩大候选集,可能触发意料之外的重载版本。
- **引用的本质**:概念——"自动解引用的 const 指针"这一视角能解释必须初始化、不能重新绑定;
坑——返回局部变量的引用,函数结束后变成悬空引用。
- **虚析构与内存泄漏**:概念——基类指针 delete 派生类对象时,只有虚析构才会走虚函数表调用到
派生类析构;坑——只要类可能被继承+可能被基类指针删除,就该把析构声明为 virtual。
- **模板与 STL 速览**:概念——泛型编程让代码脱离具体类型复用,迭代器是容器与算法之间的统一
接口;坑——容器扩容/删除元素后旧迭代器可能失效,继续用是未定义行为。
- **CMake 项目构建**:概念——CMake 是"生成构建系统的工具"而非构建系统本身,`-S -B` 生成、
`--build` 才是真正编译;坑——改了生成器相关配置(换生成器/清缓存)后要重新走一次 `-S -B`
- **Vcpkg 包管理器**:概念——一次 `vcpkg install` 配合 CMake toolchain 文件,`find_package`
即可自动定位头文件和库;坑——不是所有第三方库都必须用包管理器装,本仓库选择"隔离 Qt 手动装"
是精确控制版本/路径的另一种取舍,两种思路都要认识。
**练(95min**
- **任务卡 1 · 走一遍真实构建流程**
@@ -149,6 +186,19 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 控件创建与显示 | `p03/ch03/button_creation.cpp` |
| 内置 / 自定义 / lambda 信号槽 | `p03/ch04/builtin_signal_slot.cpp``custom_signal_slot.cpp``lambda_signal_slot.cpp` |
**核心概念与常见的坑**(对应幻灯片 `day2.html` 每个知识点前的"核心概念/常见的坑"卡片):
- **最小 Qt 程序结构**:概念——`QApplication`是唯一的事件循环拥有者,`app.exec()`阻塞进入
事件循环分发系统事件;`Q_OBJECT`触发 moc 生成信号槽/属性系统所需的元对象代码;坑——一个
进程只能有一个 `QApplication`;忘记 `exec()` 窗口一闪而过;用了信号槽却忘记 `Q_OBJECT`
会在链接阶段报 `undefined reference` 且报错不提示"缺宏"。
- **控件创建与显示**:概念——QObject 对象树父子所有权模型,parent 销毁会自动 delete 所有
子对象;坑——忘记传 parent 造成真实内存泄漏;`move()` 手动定位的控件一旦套上布局会被覆盖。
- **信号槽(内置/自定义/lambda)**:概念——观察者模式的 Qt 实现,发送者/接收者彻底解耦;
新语法 `&Class::signal` 编译期类型检查,旧字符串语法 `SIGNAL()/SLOT()` 运行时检查;连接
方式分 Direct/Queued/Auto;坑——旧语法写错不报编译错误只是运行时静默连接失败;重载信号
不加 `QOverload` 消歧义会编译报错。
**练(95min**
- **任务卡 1 · 跑通最小程序**
@@ -174,6 +224,18 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 自定义控件与布局(`QHBoxLayout` | `p03/ch08/custom_widget.cpp` |
| **QSS 界面美化(教学补充)** | `docs/teaching/examples/qss_styling/qt_qss_styling.cpp` |
**核心概念与常见的坑**
- **资源系统 .qrc**:概念——`:/...` 路径是 Qt 资源系统,资源在编译期打包进可执行文件,运行时
不依赖外部文件;坑——`.qrc` 路径与代码引用不一致会运行时静默失败(不报编译错误);忘记接入
CMake 的 `qt5_add_resources`/AUTORCC 资源系统不生效。
- **布局管理(QHBoxLayout)**:概念——布局管理器接管子控件位置/大小计算,随窗口缩放自动重排;
布局对象也遵循 QObject 父子所有权;坑——同一控件不能属于两个布局;布局设置后又用
`setGeometry`/`move` 手动改位置会被下次刷新覆盖。
- **QSS 界面美化**:概念——语法脱胎于 CSS(类型/ID 选择器、伪状态)+ 层叠继承规则,作用对象
是 QWidget 树而非 DOM;坑——ID 选择器必须先 `setObjectName``setStyleSheet` 会级联影响
所有子控件,范围失控是最容易踩的坑。
**练(95min,计算器案例——练习任务,非预建方案)**
- **任务卡 1 · 计算器雏形**
@@ -203,6 +265,18 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 自定义事件处理 / 事件过滤器 | `p03/ch09/event_override_customwidget.cpp``event_filter_mainwindow.cpp` |
| 鼠标事件 | `p03/ch09/mouse_event.cpp` |
**核心概念与常见的坑**(对应幻灯片 `day3.html`):
- **Model/View 架构**:概念——数据(`QAbstractItemModel`)与展示(`QListView`/`QTableView`
彻底拆开,同一模型可喂给多个视图;`QModelIndex` + 角色(`Qt::DisplayRole`等)统一寻址;
坑——改模型数据不发 `dataChanged`/`beginInsertRows` 信号,视图不会自动刷新。
- **事件循环:事件 vs 信号**:概念——`app.exec()` 事件循环分发 `QEvent`(复用 Day2);事件是
框架推给控件的通知,信号槽是对象间主动通知,两者不同机制;坑——主线程做耗时操作会卡住整个
事件循环(呼应 Day4 QThread)。
- **自定义事件处理 / 事件过滤器**:概念——两条拦截路径:重写 `xxxEvent()`(只影响自己)或
`installEventFilter()`(统一拦截多个控件);事件有 `accept()`/`ignore()` 状态决定是否继续
传播;坑——重写事件函数忘记调用基类实现,会丢失控件默认行为。
**练(95min**
- **任务卡 1 · Model/View 换视图**
@@ -224,6 +298,16 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 结构化二进制读写 | `p03/ch11/qdatastream_io.cpp` |
| **JSON 解析与写入(教学补充)** | `docs/teaching/examples/json_io/qt_json_parse_write.cpp` |
**核心概念与常见的坑**
- **QIODevice 统一读写抽象**:概念——`QFile`/`QTextStream`/`QDataStream` 都建立在 `QIODevice`
统一接口上,之后遇到网络/串口等设备也是同一套接口;`QTextStream`面向文本行、`QDataStream`
面向结构化二进制;坑——忘记检查 `open()` 返回值会静默失败;混淆文本/二进制模式会破坏内容。
- **JSON 序列化/反序列化**:概念——序列化/反序列化是一对互逆操作,正确性标准是"写出去再读
回来数据一致"round-trip);`QJsonValue` 是能装多种类型的变体;坑——不检查
`QJsonParseError` 会让格式错误的输入静默变成空文档;类型不匹配 `toInt()`/`toString()`
不报错只返回默认值。
**练(95min,本地数据存储案例——练习任务,非预建方案)**
- **任务卡 1 · JSON 落盘**
@@ -251,6 +335,16 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 绘图设备(`QImage`/`QPixmap`/`QPicture` | `p03/ch10/paint_device_qimage.cpp``paint_device_pixmaps.cpp``qpicture_io.cpp` |
| **QThread 多线程(教学补充)** | `docs/teaching/examples/qthread_worker/qt_thread_worker.cpp` |
**核心概念与常见的坑**(对应幻灯片 `day4.html`):
- **QPainter 绘图**:概念——Qt 绘制是框架驱动而非"想画就画",所有绘制只能发生在
`paintEvent` 里,由 Qt 按需自动调用;主动触发重绘要用 `update()`(异步排队);坑——在
`paintEvent` 之外直接画东西是未定义行为;数据变了忘记 `update()`界面不会自动重画。
- **QThread 多线程**:概念——线程亲和性(每个 QObject 归属于创建/`moveToThread`到的线程,
GUI 控件必须归属主线程);官方推荐 worker-object 模式而非继承 QThread;跨线程信号槽自动
变 Queued,无需手动加锁;坑——在工作线程直接操作 GUI 控件是未定义行为/崩溃常见来源;
`moveToThread`要在`connect``start()`之前完成。
**练(95min**
- **任务卡 1 · 画一个简单图形界面**
@@ -271,6 +365,17 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| **QPropertyAnimation 动画(教学补充)** | `docs/teaching/examples/property_animation/qt_property_animation.cpp` |
| **QStateMachine 状态机(教学补充)** | `docs/teaching/examples/state_machine/qt_state_machine.cpp` |
**核心概念与常见的坑**
- **QPropertyAnimation 动画**:概念——动画建立在属性系统(`Q_PROPERTY`,同样靠 moc 生成)
上,本质是"用缓动曲线在一段时间内不断调用属性的 setter",任何 `Q_PROPERTY` 都能被动画驱动;
坑——属性必须是真正的 `Q_PROPERTY`,随手传错属性名不会报错只是什么也不发生;动画作用对象
在播放完成前被销毁会导致悬空访问。
- **QStateMachine 状态机**:概念——让"状态"成为一等对象(`QState`),替代一堆 bool 标志位加
if-else;状态转移(`addTransition`)本质是信号触发的转移,与信号槽自然衔接;坑——忘记
`setInitialState``start()`,状态机对象存在但从未真正运行;状态未覆盖所有触发条件会导致
"卡住"。
**练(95min,交互式小游戏案例——练习任务,选做,非预建方案)**
- **任务卡 1 · 动画 + 状态机组合**
@@ -299,6 +404,14 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| 标准化考核标准 | `docs/images/assessment_standard.png` |
| 代码团队协同开发实操建议 | `docs/TRAINING_PLAN_2026.md` 「七、质量保证 (二) Git」 |
**核心概念与常见误区**(对应幻灯片 `day5.html`):
- **Git 提交习惯**:概念——每完成一个任务都提交代码并写清任务描述,提交粒度对应 Jira 任务
粒度,commit 信息是可追溯记录;误区——攒几天代码一次性提交、commit 信息写"update",历史
记录失去可追溯性。
- **标准化考核标准**:概念——项目管理评估(40%)+项目技术评估(30%)+职业素养评估(30%),技术
只占三成;误区——只顾埋头写代码、忽略项目管理和职业素养维度,另外 70% 权重被拉低。
**讨论(95min**
- **任务卡 1 · 分工复盘**
@@ -315,6 +428,14 @@ Day25 讲:练 ≈ 1:2.7Day1 模块 A 是讨论型任务(不追求"练"
| Day2–4 案例回顾 | 请 1–2 组现场展示计算器/本地存储/动画状态机小游戏 |
| OpenCV 与 AI 机器学习(可选,自学指针,无配套代码) | 方案书原文标注"可选择";如学员感兴趣,自学方向为 `cv::CascadeClassifier` 人脸检测入门,<span class="ext-ref">OpenCV 官方教程(需联网,选读)</span> |
**核心概念与常见误区**
- **案例回顾**:概念——代码走查(code review)是团队协作常规环节,讲清"为什么这么设计"比
"功能能跑"更能体现对 Day2–4 核心概念的理解;误区——只演示能跑不讲为什么,观摩组提不出有效
问题,复盘失去巩固概念的作用。
- **OpenCV 与 AI(可选)**:概念——OpenCV 是独立于 Qt 的计算机视觉库,Qt 管界面/交互、
OpenCV 管图像算法,两者通过 `cv::Mat``QImage` 转换配合。
**练(95min,综合演练)**
- **任务卡 1 · 三选一深化**