- calculator_designer_ext(Day2 增强版:表达式求值 + 括号,递归下降解析器)接入 cmake - calculator_mainwindow(Day3 上午):增强版计算器装进 QMainWindow, 菜单/状态栏/历史停靠窗,纯代码 + 显式 connect,与 mainwindow_showcase 形成坑卡对照 - calculator_mainwindow_qss(Day3 下午):上午版 + QSS 双主题美化(按键分色/伪状态/深浅切换) - 验证 mainwindow_showcase(QMainWindow 六大组件综合演示,.ui + .qrc) - OUTLINE_4DAY.md / ASSIGNMENTS.md Day3 衔接增强版起点 + 参考实现指引 - 补提交 Day2 calculator/ 与 calculator_designer/ 参考实现(CMakeLists 已引用) - 全量构建 28/28,4 目标离屏自测退出码 0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 KiB
4 天课堂设计(对齐 2026-07 新版 10 天安排)+ 中初级学员适配性评估
依据:2026-07-05 收到的新版 10 天安排(正式全文见
docs/SCHEDULE_2026_10DAY.md,简表见 §0.1),取代docs/TRAINING_PLAN_2026.md的旧执行计划作为课堂设计基准。新安排本身就是 「4 天讲授(Day1–4)+ Day5 综合案例讲解 + Day6–10 项目开发/答辩」结构, 因此本文即新基准下的正式教案大纲;此前对齐旧方案书的 5 天版OUTLINE.md保留作历史参照与素材库(其 24 张概念/坑卡在本文 全部复用)。幻灯片day1.html…day5.html已按本文重排(§9 落地状态)。 Day2–4 课堂练习/课后作业的分层(基础版+挑战版)作业单见ASSIGNMENTS.md。
0. 基准与显式假设(供随时纠偏)
0.1 新版 10 天安排(简表,讲授部分逐条对应)
| 天 | 时段 | 内容 |
|---|---|---|
| 1 | 上午讲 | 开训典礼;C++ 常用技术和框架(讲座);开发环境搭建;Makefile/CMake;面向对象基础回顾(类/对象/封装) |
| 1 | 下午讲 | C++ 核心特性(继承与多态、虚函数);内存管理(指针、引用与动态分配);STL 常用容器简介 |
| 2 | 上午讲 | Qt 概述;创建 Qt 项目;第一个 Qt 小程序 |
| 2 | 下午讲 | 信号槽机制;项目案例:简易计算器 |
| 3 | 上午讲 | QMainWindow;对话框 QDialog |
| 3 | 下午讲 | 布局管理器;常用控件 |
| 4 | 上午讲 | Qt 消息机制和事件;绘图事件及表格事件 |
| 4 | 下午讲 | 文件系统 |
| 5 | 全天 | 综合项目案例讲解(本文 §8 给出案例设计) |
| 6–10 | — | 学员项目开发;Day10 下午项目答辩 |
每个半天的固定时段结构:08:30–11:00 讲授(2.5h,产出=课堂代码+笔记+随堂练习)、 11:00–12:00 课堂练习+工程师答疑(1h);下午 13:30–16:00 讲授、 16:00–17:00 课堂作业+答疑(1h)。
0.2 显式假设
- 受众:学员已掌握 C++ 基础语法与 OOP 概念,Day1 定位是「回顾和提升」。
仍用
PRETEST.md(10 题/10 分钟,双平行卷)实测:Day1 上午 「OOP 基础回顾」开讲前发卷,按结果决定回顾环节的推进速度(分层预案见 PRETEST)。 - 讲授块内部节奏:2.5h 纯讲对中初级学员超出注意力极限,本设计把每个讲授块 切成 3–4 个「讲 25–30min + 随堂微练 10–15min」循环(新安排的产出列本就 含「课堂练习」);11:00/16:00 后的整段练习时间做当天的任务卡。
- 新安排未点名的旧主题的处置(关键决策,§4 有完整对照):QSS 并入 Day3 下午 (新安排该时段目标明含「美化」);JSON 并入 Day4 下午(「用户数据的保存与读取」 的自然载体);表格用 QTableWidget 讲、Model/View 降为延伸钩子;QThread 移入 Day5 综合案例的「提升」环节(理由与风险见 §6);动画/状态机降为自学指针; Vcpkg 降为 CMake 环节的 1 分钟概念;OpenCV 移除(旧方案书本就标注可选)。
- 工具链沿用仓库现状:host gcc/g++ + CMake/Ninja(Part1)、隔离 Qt 5.14.2(Part3),
构建命令见根
README.md;Makefile 只在 Day1 讲「CMake 生成 构建系统」时作对照概念,不单独实操。
1. 四天总览(主题 → 仓库资产映射)
| Day | 上午 | 下午 | 当日作业产出 |
|---|---|---|---|
| 1 | 开训 + C++ 技术版图 + 环境/CMake CMakeLists.txt + OOP 回顾 p01/ch04 |
继承/多态/虚析构 p01/ch04/s08 + 内存管理 p01/ch03 + STL p01/ch09 |
Part1 全绿构建 + 2 道 C++ 改错题 |
| 2 | Qt 概述 + 项目创建 + 第一个程序 p03/ch02 ch03 |
信号槽 p03/ch04 → 计算器案例 |
可运算的简易计算器 |
| 3 | QMainWindow p03/ch05 + QDialog p03/ch06 |
布局/控件 p03/ch08 + QSS examples/qss_styling |
计算器升级:主窗口化 + 美化 |
| 4 | 事件机制 p03/ch09 + 绘图 p03/ch10 + 表格 |
文件 IO p03/ch11 + JSON examples/json_io |
本地数据存储小工具(写入→重启→读回) |
四天作业刻意串成一条线:Day2 计算器 → Day3 给它套 QMainWindow+QSS → Day4 数据 落盘,Day5 综合案例是同一能力栈的完整版,学员进入 Day6 项目开发前已完整走过 3 轮「编码→构建→运行→演示」闭环。
2. 逐天设计
概念/坑卡标注:[沿用]= 取自 5 天版 OUTLINE.md 的同名卡片(内容不重抄,
以该文件为准);★[新增]= 本轮中初级误区审计(§5)补入的卡片,正文写全。
Day 1 上午:开训 / C++ 技术版图 / 环境与 CMake / OOP 回顾
讲授块切分(2.5h):
| 环节 | 内容 | 素材 |
|---|---|---|
| 开训典礼(≈40min,非教学) | 团队/实训安排/考评要求 | 组织方主持 |
| C++ 常用技术和框架(讲座 25min) | 桌面(Qt)/后端/嵌入式/游戏四大版图;C++11→20 标准演进一页图(兴趣钩子→ MODERN_CPP.md) |
无仓库代码,讲座式 |
| 环境搭建 + CMake(30min 讲 + 15min 随堂练) | 用本仓库当真教材:-S -B 生成 / --build 编译两阶段;option()、add_executable;Makefile 是 CMake 的生成目标之一(对照概念);Vcpkg 一分钟概念 |
根 CMakeLists.txt、p01/CMakeLists.txt |
| PRETEST 摸底(10min) | 发 A/B 卷,收卷即批 L1 题 | PRETEST.md |
| OOP 基础回顾(30min,按摸底结果调速) | 类/对象/封装;namespace 作用域 | p01/ch04、p01/ch03/namespace_syntax.cpp |
概念/坑卡:CMake 项目构建[沿用]、namespace 作用域[沿用]、外加——
- ★编译错误 vs 链接错误的排查分界:概念——
error:带文件行号是编译期(语法/ 类型),undefined reference无行号是链接期(缺定义/缺库/缺目标文件),排查方向 完全不同;坑——中初级学员见到undefined reference习惯回头查语法,方向就错了。 此卡是 Day2「忘写Q_OBJECT报链接错」的前置铺垫。
11:00–12:00 课堂练习:任务卡 1——独立完成 Part1 配置+构建
(cmake -S . -B build -G Ninja -DBUILD_QT_PART=OFF && cmake --build build,
144 目标全绿,能说出 option(BUILD_QT_PART) 的作用)。
Day 1 下午:继承与多态 / 内存管理 / STL 简介
| 环节 | 内容 | 素材 |
|---|---|---|
| 继承/多态/虚函数(40min 讲 + 15min 练) | 虚函数表机制、重写 vs 重载;虚析构与内存泄漏 | p01/ch04/s08/virtual_dtor_purpose.cpp;函数重载 p01/ch03/function_overload_mechanism.cpp |
| 内存管理(40min 讲 + 15min 练) | 指针/引用/动态分配;引用的本质;所有权——谁负责 delete | p01/ch03/reference_essence.cpp |
| STL 常用容器(25min 讲 + 15min 练) | vector/map/string 三件套;迭代器统一接口 | p01/ch05/class_template_basics.cpp、p01/ch09/s03/vector_iterator.cpp |
概念/坑卡:函数重载决议[沿用]、引用的本质[沿用]、虚析构与内存 泄漏[沿用]、模板与 STL 速览[沿用](含迭代器失效坑)、外加——
- ★所有权心智模型:谁负责 delete:概念——内存管理的核心问题不是「会不会 new」
而是「这块资源归谁管、由谁释放」,现代答案是 RAII/智能指针(
unique_ptr独占、shared_ptr共享,详见MODERN_CPP.md§2);坑——双重释放、 忘记释放、释放后使用三兄弟全部源于所有权不明。本卡是 Day2 Qt 对象树的前置 铺垫:Qt 用父子所有权回答同一个问题,两套体系混用有专门的坑(Day2)。
16:00–17:00 作业:从 docs/ERRATA.md 挑 2 条与今天知识点相关的记录(虚析构/引用
/重载类),在源文件里理解「wiki 原文错在哪、为什么」,各写一句话解释;选做——用
tools/std_probe.py 验证一个版本差异点(对照 docs/VERSION_NOTES.md)。
Day 2 上午:Qt 概述 / 创建 Qt 项目 / 第一个 Qt 小程序
| 环节 | 内容 | 素材 |
|---|---|---|
| Qt 概述(25min) | Qt 是什么/能做什么;Qt 5.14 vs 系统 Qt 隔离(本仓库 .qt514/ 的做法);模块结构 Core/Gui/Widgets |
根 CMakeLists.txt 的 Qt 版本断言 |
| 创建 Qt 项目(30min 讲 + 15min 练) | CMake 方式创建(find_package(Qt5)、AUTOMOC);构建开关 -DBUILD_QT_PART=ON |
p03/CMakeLists.txt、p03/ch02/CMakeLists.txt |
| 第一个 Qt 小程序(40min 讲 + 20min 练) | QApplication + exec() 事件循环;控件创建与显示;QObject 对象树 |
p03/ch02/minimal_qt_app.cpp、p03/ch03/button_creation.cpp |
概念/坑卡:最小 Qt 程序结构[沿用](含忘 Q_OBJECT 链接错——正好接 Day1
链接错误卡)、控件创建与显示[沿用](对象树/parent)、外加——
- ★栈对象与父子所有权打架:概念——Qt 父子树在 parent 析构时
delete所有子 对象,这要求子对象必须建在堆上;坑——把带 parent 的控件建在栈上 (QPushButton btn(&window);),作用域结束栈析构一次、parent 再 delete 一次 → 双重释放崩溃。与 Day1 所有权卡呼应:Qt 树管的对象不要再用智能指针/栈/手动 delete 去管,一个对象只能有一个所有者。
11:00–12:00 课堂练习:跑通 minimal_qt_app 与 button_creation
(QT_QPA_PLATFORM=offscreen tools/run_qt.sh <target> 退出码 0);改造:窗口
标题、按钮文字换成自己的学号姓名(第一次触碰 QString 中文——为下午的编码卡埋点)。
Day 2 下午:信号槽机制 → 案例:简易计算器
| 环节 | 内容 | 素材 |
|---|---|---|
| 信号槽(50min 讲 + 20min 练) | 观察者模式;内置/自定义/lambda 三种写法;新旧语法对比;连接方式 Direct/Queued/Auto | p03/ch04/builtin_signal_slot.cpp、custom_signal_slot.cpp、lambda_signal_slot.cpp |
| 计算器案例(40min 带练) | 数字/运算键盘 + 点击信号槽 + 结果显示;布局用教师提供的 QGridLayout 脚手架「先用后学」(布局原理 Day3 下午讲透,今天只求能排出键盘) |
p03/ch03 + p03/ch04 + 教师参考实现 examples/calculator/(另有 examples/calculator_designer/ Qt Designer .ui 对照版,含「自动连接静默失效」坑点) |
概念/坑卡:信号槽三种写法[沿用](含旧语法静默失败、QOverload 消歧义)、外加——
- ★lambda 槽的生命周期与第五参数:概念——
connect第五参数(context object) 决定连接的生存期,lambda 槽应传 context,对象销毁连接自动断开;坑——lambda 按引用 捕获局部变量、或捕获this而不传 context,对象销毁后信号再来就是悬空访问——这是 从「能用 lambda」到「敢在项目里用 lambda」之间最大的坑。 - ★重复 connect 导致槽触发多次:概念——
connect每调一次新增一条连接,同一对 信号槽连两次槽就被调两次(Qt::UniqueConnection可防重);坑——把connect写在 会被多次执行的函数里,现象是「点一次按钮弹两次框」,学员往往去查按钮而不是查连接。 - ★QString 与中文编码:概念——
QString内部是 UTF-16,与std::string(字节串) 互转要经toUtf8()/fromUtf8();坑——源码不存成 UTF-8、或用QString(char*)隐式转换中文字面量,界面就是乱码。中文教学环境第一天写界面必踩,上午练习的 学号姓名改造就是现场复现点。
16:00–17:00 作业:完成计算器——至少支持两个数 + 加减乘除,结果正确显示在
QLabel/QLineEdit;界面不重叠、按钮可点击(验收同 5 天版计算器任务卡 1)。
Day 3 上午:QMainWindow / 对话框 QDialog
| 环节 | 内容 | 素材 |
|---|---|---|
| QMainWindow(45min 讲 + 20min 练) | 主窗口架构:菜单栏/工具栏/状态栏/中心部件/停靠窗 | p03/ch05/central_widget.cpp、dock_widget.cpp;综合演示 examples/mainwindow_showcase/(极简文本编辑器,.ui 表单 + 自动连接,覆盖 wiki ch05 六大组件) |
| QDialog(45min 讲 + 20min 练) | 模态 vs 非模态(三种非模态写法对比:栈/堆/WA_DeleteOnClose);标准对话框 QMessageBox/QFileDialog |
p03/ch06/modal_dialog.cpp、modeless_dialog_stack.cpp、modeless_dialog_heap.cpp、modeless_dialog_deleteonclose.cpp、message_box_question.cpp、file_dialog.cpp |
概念/坑卡(本节两张为本文新写,5 天版未覆盖 ch05/ch06):
- QMainWindow 结构:概念——QMainWindow 不是「大号 QWidget」,它有固定的区域
布局协议(菜单/工具/状态/中心/停靠各就其位),中心部件必须
setCentralWidget显式安放;坑——直接往 QMainWindow 上addWidget/摆控件而不设中心部件,布局行为 不可预期;菜单动作QAction忘了connect到槽,菜单显示正常点了没反应。 - 模态与非模态的生命周期:概念——模态
exec()阻塞等结果、返回值即用户选择; 非模态show()立即返回,对话框对象必须活过函数作用域(堆 + parent,或WA_DeleteOnClose自清理);坑——栈上建非模态对话框show()完函数一返回就 析构,窗口一闪而过——p03/ch06三个 modeless 版本正是这个坑的对照教材,也是 Day2 栈/堆所有权卡的第三次复现。
11:00–12:00 课堂练习:以 Day2 增强版计算器(examples/calculator_designer_ext/)为起点,套上 QMainWindow——加菜单「帮助→关于」弹
QMessageBox;加一个「历史」停靠窗(可先放空 QLabel)。参考实现:
examples/calculator_mainwindow/(纯代码
建菜单 + 显式 connect,与 mainwindow_showcase 的 .ui 自动连接形成坑卡对照)。
衔接说明:Day2 增强版
CalculatorDesigner已是独立QWidget,Day3 上午只做 「外壳升级」——setCentralWidget把它装进QMainWindow,核心求值逻辑不动。 唯一新增是CalculatorDesigner加一个evaluated信号供历史停靠窗订阅(Day2 信号槽知识的复用)。详见参考实现 README。
Day 3 下午:布局管理器 / 常用控件(+QSS 美化)
| 环节 | 内容 | 素材 |
|---|---|---|
| 布局管理器(40min 讲 + 15min 练) | QHBox/QVBox/QGrid;嵌套布局;伸缩因子——回收 Day2 计算器脚手架,讲透当时「先用后学」的部分 | p03/ch08/custom_widget.cpp |
| 常用控件(35min 讲 + 15min 练) | QLabel 文本/HTML/图片、QLineEdit、按钮族;资源系统 .qrc |
p03/ch08/label_text_html.cpp、label_pixmap.cpp、label_movie.cpp |
| QSS 界面美化(25min 讲 + 20min 练) | 选择器/伪状态/层叠——对应新安排「自适应排版及美化」目标 | docs/teaching/examples/qss_styling/qt_qss_styling.cpp + README;作业线参考 examples/calculator_mainwindow_qss/(上午版 + 双主题 QSS) |
概念/坑卡:布局管理[沿用](同控件不能属两个布局;布局后 setGeometry 被
覆盖)、资源系统 .qrc[沿用](路径静默失败/AUTORCC)、QSS 美化[沿用]
(ID 选择器要 setObjectName;setStyleSheet 级联失控)。
16:00–17:00 作业:计算器升级——数字键/运算键/等号键用 QSS 区分颜色,至少 1 个按钮
有 :hover 或 :pressed 效果;整体布局改为可随窗口缩放(验收同 5 天版 QSS 任务卡)。
参考实现:examples/calculator_mainwindow_qss/(在
Day3 上午版基础上只加 QSS,演示「美化与逻辑正交」)。
Day 4 上午:Qt 消息机制和事件 / 绘图事件及表格事件
| 环节 | 内容 | 素材 |
|---|---|---|
| 事件循环与派发(35min 讲 + 15min 练) | exec() 事件循环回收 Day2 概念;事件 vs 信号槽两套机制;主线程阻塞=界面冻结(为 Day5 QThread 提升埋点) |
p03/ch02/minimal_qt_app.cpp |
| 事件拦截(30min 讲 + 15min 练) | 重写 xxxEvent() vs installEventFilter();accept()/ignore() 传播 |
p03/ch09/event_override_customwidget.cpp、event_filter_mainwindow.cpp、mouse_event.cpp |
| 绘图事件(30min 讲 + 15min 练) | paintEvent + QPainter;update() 异步重绘;绘图设备一瞥 |
p03/ch10/qpainter_basic.cpp(设备类 paint_device_*.cpp 作参考) |
| 表格(15min 演示) | QTableWidget 单元格填充与 cellClicked/itemChanged 事件(item 类控件够项目用);Model/View 架构一页概念 + 延伸钩子 |
docs/teaching/examples/table_widget/qt_table_widget_basics.cpp(M/V 钩子:examples/model_view/) |
概念/坑卡:事件循环:事件 vs 信号[沿用]、自定义事件处理/事件过滤器
[沿用](重写忘调基类丢默认行为)、QPainter 绘图[沿用](paintEvent
之外绘制 UB;忘 update() 不重画)、Model/View 架构[沿用,降为概念页]。
11:00–12:00 课堂练习:给控件装事件过滤器拦截鼠标按下并打印坐标;在 paintEvent
里画一个组合图形(棋盘格或仪表盘刻度)。
Day 4 下午:文件系统(+JSON)
| 环节 | 内容 | 素材 |
|---|---|---|
| 文件读写(40min 讲 + 20min 练) | QFile/QTextStream/QDataStream;QIODevice 统一抽象 |
p03/ch11/qfile_basic.cpp、qtextstream_io.cpp、qdatastream_io.cpp |
| JSON 解析与写入(35min 讲 + 20min 练) | round-trip 正确性标准;QJsonDocument/Object/Array/Value |
docs/teaching/examples/json_io/qt_json_parse_write.cpp + README |
概念/坑卡:QIODevice 统一读写抽象[沿用](open() 不检查静默失败)、
JSON 序列化/反序列化[沿用](QJsonParseError 不检查静默空文档;类型不匹配
返回默认值不报错)、外加——
- ★相对路径与工作目录:概念——
QFile("data.json")的相对路径基于进程当前 工作目录,不是源码目录也不一定是可执行文件目录;IDE、终端、tools/run_qt.sh三种跑法工作目录可能各不相同;坑——「IDE 里能读到文件,命令行跑就说不存在」, 中初级学员几乎必问。正解:QCoreApplication::applicationDirPath()拼路径,或 只读资源走.qrc(呼应 Day3 资源卡)。 - ★文本编码再遇(文件版):概念——
QTextStream默认编码随平台/区域设置而变 (Qt 5 默认本地编码),跨平台交换文本必须显式setCodec("UTF-8");坑——Windows 写的文件 Linux 读出乱码(或反过来)。与 Day2 的 QString 编码卡同根源、隔两天 第二次出现,刻意间隔重复形成「编码要显式指定」的条件反射。
16:00–17:00 作业:本地数据存储小工具——「学员信息」结构(姓名/成绩/标签)增加记录 并保存到 JSON 文件,重启程序读回全部记录(至少 2 条、字段不丢,验收同 5 天版 存储任务卡 2)。这是 Day5 综合案例的直接前身。
3. Day5 综合项目案例讲解(全天,衔接设计)
新安排 Day5 的目标是「通过综合案例讲解 Qt 开发流程、规范及方法」。建议案例: 「学员信息管理器」——把四天作业线收束成完整小软件,正好覆盖全部已学内容并 补上项目开发前的最后三块拼图:
| 时段 | 内容 | 覆盖 |
|---|---|---|
| 上午 1 | 需求拆解 → 界面骨架:QMainWindow + 菜单/工具栏 + QTableWidget 列表 + 增改对话框 | Day3 全部 + Day4 表格 |
| 上午 2 | 数据层:记录结构 ↔ QJson 序列化 ↔ 落盘读回;信号槽把界面和数据接起来 | Day4 下午 + Day2 |
| 下午 1 | 提升:QThread 防卡界面——导入大文件时界面不冻结(worker 对象模式、跨线程不碰 GUI) | docs/teaching/examples/qthread_worker/ + README(旧 5 天版 D4A 的概念/坑卡照用) |
| 下午 2 | 开发流程与规范:Git 提交粒度(对应任务粒度、信息可追溯,忌"update");代码走查怎么做;考评三维度(管理/技术/素养);分组定项目方向 | docs/TRAINING_PLAN_2026.md 质量保证节 + docs/images/ 三图 |
| 兴趣钩子(穿插) | 动画/状态机各 5min 演示(给界面加转场动效的方向) | examples/property_animation/、state_machine/ |
QThread 放 Day5 而非砍掉的理由:「主线程阻塞=界面冻结」是学员项目里最高频的 崩溃/卡死来源,新安排 Day1–4 没有它的位置,但综合案例的「导入数据」情节是它 最自然的出场时机;且 Day4 上午事件循环卡已埋点,Day5 只需 60–70 分钟就能讲透 worker 模式三件套(亲和性/moveToThread 时序/跨线程信号槽自动 Queued)。
4. 评估 A:新安排条目覆盖核对 + 旧主题去向
新安排讲授条目 → 本设计位置:逐条对齐(§2 各表第一列即新安排原文条目), 无遗漏;「Makefile/CMake」按 §0.2 假设 4 以 CMake 实操为主、Makefile 为对照概念。
旧 5 天版有、新安排未点名的主题的去向:
| 旧主题 | 去向 | 理由 |
|---|---|---|
| QSS 美化 | Day3 下午(正式讲授) | 新安排 Day3 下午目标原文含「美化」;且计算器案例线需要它 |
| JSON | Day4 下午(正式讲授) | 「用户数据的保存与读取」的事实标准载体;项目实作必用 |
| Model/View | Day4 上午概念页 + 延伸钩子 | 项目层面 QTableWidget 够用;完整 M/V 对中初级学员超纲 |
| QThread 多线程 | Day5 提升环节(保留讲授) | 见 §3 论证;完全砍掉是项目期最大风险点 |
| 动画/状态机 | Day5 钩子 + 自学指针 | 项目使用频率低;示例与 README 完整保留 |
| Scrum/团队协同/考核标准 | 开训典礼(组织方)+ Day5 下午 2 | 讲授权重下调,但 Git 习惯与考评三维度保留在进项目前最后一课 |
| Vcpkg | Day1 CMake 环节 1 分钟概念 | 新安排未点名;保留「包管理器是什么」的认知即可 |
| OpenCV | 移除(不再作自学指针占课时) | 旧方案书即标注可选;新安排无此条 |
5. 评估 B:中初级学员常见误区/盲点覆盖审计(核心交付)
审计画像:「有一定 C++ 基础」= PRETEST L1 全对、L2 部分对的学员。逐条核对三个 层面的高频误区是否有对应「概念/坑」卡。✔=沿用 5 天版已覆盖卡;★=本轮新增; ☆=本文为 ch05/ch06 新写;—=有意不覆盖(附理由)。
C++ 语言层(Day1 集中处理):
| 误区/盲点 | 覆盖 | 位置 |
|---|---|---|
| 引用可空/可重绑、值传递 vs 引用传递、悬空引用 | ✔ | Day1 下午 + PRETEST L1 |
| 虚析构缺失泄漏、多态机制、重写 vs 重载 | ✔ | Day1 下午 + PRETEST L2/L3 |
| 重载决议二义性、隐式转换扩大候选集 | ✔ | Day1 下午 + PRETEST L2 |
| 迭代器失效 | ✔ | Day1 下午 STL 卡 |
头文件 using namespace 污染 |
✔ | Day1 上午 namespace 卡 |
| 「谁负责 delete」所有权模型缺失 | ★ | Day1 下午新卡(内存管理环节,位置比旧版更贴切) |
| 编译错误 vs 链接错误分不清 | ★ | Day1 上午新卡 |
| static 初始化顺序、const 细则、移动语义细节 | — | 项目实作用不到临界深度;MODERN_CPP.md 作自学 |
Qt 框架层(Day2–4 + Day5):
| 误区/盲点 | 覆盖 | 位置 |
|---|---|---|
忘 Q_OBJECT → 链接错且不提宏 |
✔ | Day2 上午(有 Day1 链接卡打底) |
忘 exec() 窗口一闪而过、多个 QApplication |
✔ | Day2 上午 |
| 忘传 parent 泄漏 | ✔ | Day2 上午 |
| 栈上建带 parent 的控件 → 双重释放 | ★ | Day2 上午新卡 |
| 非模态对话框建在栈上一闪而过 | ☆ | Day3 上午新卡(同一所有权误区第三次复现,ch06 三个 modeless 对照文件是现成教材) |
| lambda 槽捕获悬空 / 缺 context 参数 | ★ | Day2 下午新卡 |
| 重复 connect → 槽触发多次 | ★ | Day2 下午新卡 |
| 旧字符串语法静默失败、重载信号消歧义 | ✔ | Day2 下午 |
| QString/std::string 混淆、中文乱码 | ★ | Day2 下午新卡(上午练习已现场埋复现点) |
| QMainWindow 不设中心部件、QAction 忘连接 | ☆ | Day3 上午新卡 |
同控件属两个布局、布局后手动 setGeometry 被覆盖 |
✔ | Day3 下午 |
.qrc 路径错静默失败 |
✔ | Day3 下午 |
| QSS 级联失控、ID 选择器要 objectName | ✔ | Day3 下午 |
| 重写事件函数忘调基类 | ✔ | Day4 上午 |
paintEvent 之外绘制 UB、忘 update() |
✔ | Day4 上午 |
| 改模型不发信号视图不刷新 | ✔(概念页) | Day4 上午 |
open() 不检查、JSON 解析错误静默 |
✔ | Day4 下午 |
| 相对路径随工作目录漂移 | ★ | Day4 下午新卡 |
| QTextStream 默认编码平台相关 → 跨机乱码 | ★ | Day4 下午新卡 |
| 工作线程碰 GUI 崩溃、moveToThread 时序 | ✔ | Day5 提升环节(Day4 上午已埋「阻塞=冻结」认知) |
| Qt Designer/.ui 工作流 | — | 本课程纯代码路线(仓库示例均无 .ui);项目期按需补 |
工程/协作层:
| 误区/盲点 | 覆盖 | 位置 |
|---|---|---|
| CMake「生成 vs 构建」两阶段混淆 | ✔ | Day1 上午 |
| 新标准特性 ≠ 工具链可用 | ✔ | Day1 讲座钩子 + std_probe.py 作业选做 |
| commit 粒度失控、信息写"update" | ✔ | Day5 下午 2(进项目前最后一课,即时生效) |
| 只重技术忽略考评其余维度 | ✔ | Day5 下午 2 |
审计结论:共 10 张新卡(★8 + ☆2),集中三条主线:①所有权与生命周期 (谁 delete → 栈控件双重释放 → 非模态对话框一闪而过 → lambda 捕获悬空,四天内 四次复现同一心智模型,这是「学过 C++ 语法」与「写得出不崩的 Qt 程序」之间最大的 鸿沟);②编码与路径(中文乱码 Day2 → 文件乱码 Day4 → 工作目录 Day4,中文教学 环境必踩且旧版完全空白);③连接语义(重复 connect、context 参数,现象诡异、 自查困难,教了能省项目期大量答疑)。新安排把 C++ 扩到整天,反而让 ①在 Day1 就能 立住地基——比旧 5 天版(C++ 只有半天)对中初级学员更友好。
6. 评估 C:Day6–10 项目开发就绪度
| 项目必备能力 | 训练强度 | 位置 |
|---|---|---|
| 主窗口+菜单+对话框的标准桌面骨架 | 讲+练+案例 | Day3 + Day5 |
| 控件/布局/美化 | 讲+练+作业(计算器线) | Day2–3 |
| 对象间通信(信号槽三种写法) | 讲+练 | Day2 |
| 数据持久化(JSON round-trip) | 讲+练+作业+案例 | Day4–5 |
| 表格类数据展示 | 演示+案例 | Day4–5 |
| 事件拦截/自绘 | 讲+练 | Day4 |
| 耗时操作不卡 UI | 讲+案例(Day5 提升) | Day4 埋点 + Day5 |
| 崩溃自查(所有权/编码/连接三主线) | 10 张坑卡 + 四次间隔复现 | Day1–4 贯穿 |
| Git/流程/考评认知 | 讲 | Day5 |
| 综合组装 | 全程案例走查 | Day5 |
结论:就绪度充分,且作业线(计算器→主窗口化→数据落盘→综合案例)保证每个学员 进项目前至少完成 3 个递进的可运行程序。两个前提条件:① PRETEST 摸底通过(不通过 则触发 PRETEST 分层预案,Day1 下午减少 STL 时长、加固 OOP);② Day5 必须保住 QThread 提升环节——若 Day5 案例讲解超时挤掉它,项目期「界面冻结/跨线程崩溃」 答疑成本会数倍返还,这是本设计标记的最高优先级保底项。
7. 评估 D:高阶兴趣钩子(每处 1–2 分钟点到 + 自学入口)
| Day | 钩子(挂在当天刚学的内容上) | 自学入口 |
|---|---|---|
| 1 | C++ 不是停滞的语言:11「几乎新语言」→ 20 四大件 → 26 反射;现场用 std_probe.py 编译验证一个新特性 |
MODERN_CPP.md、MODERN_CPP_20PLUS.md(含本机 GCC 实测矩阵) |
| 2 | 信号槽的幕后:打开 build/ 里真实的 moc_*.cpp 看 moc 生成了什么 |
本仓库构建产物 + Qt 元对象系统文档 |
| 3 | QSS 与前端 CSS 的同源关系;Qt Designer/QML 是另一条 UI 路线 | Qt 官方 Style Sheets 文档 |
| 4 | 今天的 QTableWidget 背后是完整的 Model/View 架构(数据/展示彻底解耦、一模型多视图) | examples/model_view/ + Qt Model/View 长文 |
| 5 | QtConcurrent/线程池是 QThread 的更高抽象;动画/状态机给界面加转场 | examples/property_animation/、state_machine/、MODERN_CPP_20PLUS.md §协程 |
设计原则:钩子全部是当天内容的自然延伸(学了信号槽→看 moc 产物;学了表格→ 看 Model/View),不做空降的「高级话题清单」——好奇心要挂在已有的钩子上。
8. 风险与缓解
| 风险 | 缓解 |
|---|---|
| 2.5h 讲授块对中初级学员过长 | §0.2 假设 2 的「讲 25–30 + 练 10–15」循环切分;随堂微练全部有明确产出(跑通/改造/复现坑) |
| Day2 下午计算器早于布局课(新安排固有顺序) | 教师提供 QGridLayout 脚手架「先用后学」,Day3 下午回收讲透;脚手架片段随幻灯片提供 |
| Day5 案例讲解超时挤掉 QThread 提升 | 上午严格按 §3 时段推进;万一超时,砍动画/状态机钩子而非 QThread(§6 保底项) |
| PRETEST 摸底不达标 | Day1 下午 STL 环节让位 OOP 加固(PRETEST 分层预案);新安排 C++ 占整天,回旋余地本就比旧 5 天版大 |
已补 examples/table_widget/qt_table_widget_basics.cpp,离屏验证通过 |
9. 落地清单(2026-07-05 已全部执行)
- ✅ 幻灯片重排:
day1.html…day5.html已按本文 §2/§3 重组(Day1 全 C++、Day3 新增 ch05/ch06、Day5 改综合案例结构);10 张新卡已按custom.css现有.concept-box/.pitfall-box样式补入(幻灯片内标注 ★/☆),「大纲↔幻灯片 一一对应」约定保持。 - ✅ 坑点最小复现示例已补入
docs/teaching/examples/(手工维护区,不影响生成器):pitfall_stack_widget(--crash触发真实双重释放崩溃)、pitfall_lambda_capture(--dangle触发真实悬空访问)、pitfall_double_connect(确定性 2 次→1 次对比)、table_widget(QTableWidget 最小示例)。默认运行均为正确写法、离屏验证退出码 0。 - ✅ Day5 综合案例参考实现:
docs/teaching/examples/student_manager/(QMainWindow + QTableWidget + 对话框 + JSON round-trip + QThread 后台导入; 离屏自测模式自动校验「写入→读回」与导入闭环)。 3.1 ✅ Day2 案例参考实现:docs/teaching/examples/calculator/(代码QGridLayout版)+docs/teaching/examples/calculator_designer/(Qt Designer.ui对照版,含自动连接on_<objectName>_<signal>静默失效坑点);两版业务 逻辑一致,离屏自测覆盖加减乘除/链式运算/除零/退格 5 组用例。 3.2 ✅ Day2 增强版计算器:docs/teaching/examples/calculator_designer_ext/(在 Designer 版基础上把「立即计算」升级为「表达式求值」——独立ExpressionEvaluator递归下降解析器,支持运算符优先级 + 括号含嵌套/未闭合自动补全;双显示区;离屏自测 9 组用例含2+3*4=14、(2+3)*4=20)。作为 Day3 的起点。 3.3 ✅ Day3 上午 QMainWindow 组件综合演示:docs/teaching/examples/mainwindow_showcase/(极简文本编辑器形态,.ui表单 +.qrc资源 +on_<obj>_<sig>自动连接,覆盖 wiki ch05 的 5.1–5.6 六大组件;离屏退出码 0)。教师讲组件协议时用,与下方calculator_mainwindow形成.ui/自动连接 vs 纯代码/显式 connect 的坑卡对照。 3.4 ✅ Day3 上午参考实现:docs/teaching/examples/calculator_mainwindow/(把 Day2 增强版CalculatorDesigner装进QMainWindow:菜单/状态栏/历史停靠窗;CalculatorDesigner仅加evaluated信号 +loadExpression方法供历史订阅/回填; 纯代码建菜单 + 显式 connect;离屏自测 9 组计算 + 历史追加/双击回填/清空)。 3.5 ✅ Day3 下午参考实现:docs/teaching/examples/calculator_mainwindow_qss/(上午版 + QSS 双主题美化:按键按功能分色 +:hover/:pressed+ 深/浅主题切换; 与上午版仅mainwindow.{h,cpp}差异,演示「美化与逻辑正交」;离屏自测含主题切换 改变styleSheet的断言)。 - ✅ 新 10 天安排正式文本已落入
docs/SCHEDULE_2026_10DAY.md;OUTLINE.md§0 与幻灯片index.html已补两版关系说明。