教案对齐官方方案书:重写为 5 天 C++/Qt 教学设计,补齐 6 个 Qt 技术缺口示例
- docs/teaching/OUTLINE.md、slides/day1-5.html、index.html:替换此前自定义的 4 天方案,严格对齐 docs/TRAINING_PLAN_2026.md「C++方向」Day1-5 课堂内容 (Day6-10 为纯项目实作,不在教案范围) - docs/teaching/examples/:官方方案书要求但仓库 p03/(wiki 抓取内容) 未覆盖的 QSS/Model-View/JSON/QThread/QPropertyAnimation/QStateMachine 六个技术点, 各补一个最小可运行示例 + README 教学文档,均已离屏验证跑通;手工维护, 不属于 gen_part3.py 生成产物 - 根 CMakeLists.txt:接入 docs/teaching/examples 构建(BUILD_QT_PART 分支内), 不改动生成器管理的 p01/p03 CMakeLists - 任务卡改为目标/验收标准/基础知识参考三段式模板,custom.css 配套新增样式 - docs/teaching/PRETEST.md:10 题 10 分钟 C++ 摸底测验,验证教案假定的受众 基础是否成立,并与 OUTLINE.md §0 的分层预案挂钩
This commit is contained in:
+152
-250
@@ -2,7 +2,7 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Day 1 · C++ 对 C 的扩展 + 类和对象基础</title>
|
||||
<title>Day 1 · 开训 + C++ 回顾/工具链</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="reveal/reveal.css">
|
||||
<link rel="stylesheet" href="reveal/theme.css">
|
||||
@@ -15,161 +15,88 @@
|
||||
|
||||
<section>
|
||||
<h1>Day 1</h1>
|
||||
<h3>C++ 对 C 的扩展 + 类和对象基础</h3>
|
||||
<p class="module-badge">Qt 方向实训 · 第 1 / 4 天 · 讲:练 ≈ 1:2.7</p>
|
||||
<h3>开训 + C++ 回顾/工具链</h3>
|
||||
<p class="module-badge">C++/Qt 方向实训 · 第 1 / 5 天 · 对齐官方方案书 Day1</p>
|
||||
<ul>
|
||||
<li>模块 A(3 课时):C++ 对 C 的扩展 —— 强化,非入门</li>
|
||||
<li>模块 B(3 课时):类和对象基础</li>
|
||||
<li>模块 A(3 课时):团队建设 / 敏捷 Scrum / C++ 在企业中的应用(讨论型,无编码)</li>
|
||||
<li>模块 B(3 课时):C++ 环境搭建 / 高级程序回顾 / CMake / Vcpkg(压缩讲解)</li>
|
||||
</ul>
|
||||
<p><small>大纲:<a class="filelink" href="../OUTLINE.md">docs/teaching/OUTLINE.md</a></small></p>
|
||||
<p><small>本教案假定学员已掌握 C++ 基础语法与 OOP 概念——方案书对今天下午的
|
||||
官方定位是"回顾和提升",不是零基础教学。今天开始的 5 天覆盖方案书 C++方向
|
||||
Day1–5 全部课堂内容,Day6–10 是纯项目实作。</small></p>
|
||||
<div class="verify-box" style="font-size:0.5em;">
|
||||
<h4>模块 B 开始前:10 分钟摸底测验</h4>
|
||||
<p>这条假设不是拍脑袋定的——建议模块 B 讲授前先用
|
||||
<a class="filelink" target="_blank" href="../PRETEST.md">docs/teaching/PRETEST.md</a>
|
||||
(10 题、10 分钟)实测一次,按结果决定原节奏推进还是回退到语法讲解。</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ===================== 模块 A:讲 ===================== -->
|
||||
<section>
|
||||
<section>
|
||||
<p class="module-badge">模块 A · 讲授 35min</p>
|
||||
<h2>C++ 对 C 的扩展 <span class="tag tag-lecture">讲</span></h2>
|
||||
<p>已默认你熟悉这些语法——今天讲「为什么」,不讲「怎么写」:</p>
|
||||
<h2>团队建设 / 敏捷 Scrum / C++ 企业应用 <span class="tag tag-lecture">讲</span></h2>
|
||||
<ul>
|
||||
<li>namespace 的作用域本质</li>
|
||||
<li>函数重载的决议机制</li>
|
||||
<li>const 的本质 vs #define</li>
|
||||
<li>引用的本质(语法糖视角)</li>
|
||||
<li>三目运算符可否作左值 —— 纯版本差异</li>
|
||||
<li>团队建设与文化、实训安排与考评要求</li>
|
||||
<li>项目开发过程管理全景(JIRA / Git / OASIS / Wiki)</li>
|
||||
<li>敏捷 Scrum 项目开发管理</li>
|
||||
<li>C++ 在企业中的应用</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p class="module-badge">强化点 1 / 5</p>
|
||||
<h3>namespace 为什么不能定义在函数体内 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
namespace A{
|
||||
int a = 10;
|
||||
}
|
||||
namespace B{
|
||||
int a = 20;
|
||||
}
|
||||
void test(){
|
||||
cout << "A::a : " << A::a << endl;
|
||||
cout << "B::a : " << B::a << endl;
|
||||
}
|
||||
</code></pre>
|
||||
<p><small>作用域是「文件级」概念,不是「语句顺序」——wiki 原文把 namespace
|
||||
写进了函数体内,编译不过;出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/namespace_syntax.cpp">p01/ch03/namespace_syntax.cpp</a>,
|
||||
修正记录 <span class="filelink">ERRATA.md [58954439:3/6/7]</span></small></p>
|
||||
<h3>实习实训服务流程 <span class="tag tag-lecture">讲</span></h3>
|
||||
<img src="../../images/training_service_flow.png" style="max-height:480px;">
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../TRAINING_PLAN_2026.md">docs/TRAINING_PLAN_2026.md</a>
|
||||
「六、实习实训服务流程」——需求分析→需求评审→项目研发/代码实现→阶段评审→
|
||||
项目测试/交付,这就是接下来 Day6–10 项目实作要走的完整流程。</small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p class="module-badge">强化点 2 / 5</p>
|
||||
<h3>函数重载:二义性从哪来 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
void MyFunc(string b){ cout << "b: " << b << endl; }
|
||||
// 函数重载碰上默认参数
|
||||
void MyFunc(string b, int a = 10){ cout << "a: " << a << " b:" << b << endl; }
|
||||
|
||||
int main(){
|
||||
// MyFunc("hello"); // 二义:两个重载同等匹配
|
||||
MyFunc("hello", 20); // 显式给第二参才能消歧义
|
||||
}
|
||||
</code></pre>
|
||||
<p><small>重载决议只看「能否唯一确定最佳匹配」,默认参数不参与决议——
|
||||
出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/function_overload_basics_2.cpp">p01/ch03/function_overload_basics_2.cpp</a>,
|
||||
<span class="filelink">ERRATA.md [58954439:42] ambiguous-overload</span></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p class="module-badge">强化点 3 / 5</p>
|
||||
<h3>const 的本质 vs #define <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
const int constA = 10;
|
||||
int main(){
|
||||
int* p = (int*)&constA;
|
||||
*p = 200; // 绕过 const 的“建议性”检查——编译期常量 ≠ 只读内存
|
||||
}
|
||||
</code></pre>
|
||||
<p><small>const 是「编译期类型检查」,不是「运行期内存保护」;#define 只是文本替换,
|
||||
没有类型、没有作用域。出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/const_diff_summary.cpp">p01/ch03/const_diff_summary.cpp</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p class="module-badge">强化点 4 / 5</p>
|
||||
<h3>引用的本质 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
void testFunc(int& ref){
|
||||
ref = 100; // 编译器内部转换为 *ref = 100
|
||||
}
|
||||
int main(){
|
||||
int a = 10;
|
||||
int& aRef = a; // 自动转换为 int* const aRef = &a —— 这也是引用必须初始化的原因
|
||||
aRef = 20; // 内部转换为 *aRef = 20
|
||||
}
|
||||
</code></pre>
|
||||
<p><small>把引用当成「自动解引用的 const 指针」来理解,很多“为什么引用不能重新绑定”
|
||||
的疑惑会自然消失。出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/reference_essence.cpp">p01/ch03/reference_essence.cpp</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p class="module-badge">强化点 5 / 5 · 版本差异</p>
|
||||
<h3>三目运算符能否作左值 —— 纯版本问题 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
// C(p01/ch03/ternary_operator.c):三目表达式返回右值
|
||||
(a > b ? a : b) = 100; // C 中非法
|
||||
|
||||
// C++(p01/ch03/ternary_operator.cpp):三目表达式返回左值引用
|
||||
(a > b ? a : b) = 100; // C++ 中合法,b 会被改写
|
||||
</code></pre>
|
||||
<p><small>现场演示:<code class="filelink">tools/std_probe.py --lang c --file
|
||||
p01/ch03/ternary_operator.c --standards c89,c99,c11,c17 --pedantic-errors</code>
|
||||
—— 对照 <span class="filelink">docs/VERSION_NOTES.md §2</span></small></p>
|
||||
<h3>质量保证:四平台一标准 <span class="tag tag-lecture">讲</span></h3>
|
||||
<img src="../../images/quality_four_platforms.png" style="max-height:420px;">
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../TRAINING_PLAN_2026.md">docs/TRAINING_PLAN_2026.md</a>
|
||||
「七、质量保证」——JIRA(任务跟踪)+ Git(版本管理)+ Wiki 知识库 +
|
||||
OASIS 绿洲实训管理平台,是接下来项目实作阶段的四个协作工具。</small></p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- ===================== 模块 A:练 ===================== -->
|
||||
<!-- ===================== 模块 A:讨论(无编码) ===================== -->
|
||||
<section>
|
||||
<section>
|
||||
<p class="module-badge">模块 A · 练习 95min</p>
|
||||
<h2>动手:ch03 强化练习 <span class="tag tag-practice">练</span></h2>
|
||||
<p>目录:<a class="filelink" target="_blank" href="../../../p01/ch03">p01/ch03/</a>
|
||||
(47 个源文件,本节任务只挑一部分,其余留作参考自学)</p>
|
||||
<p class="module-badge">模块 A · 讨论 95min(分组,非编码)</p>
|
||||
<h2>动手:分组讨论 <span class="tag tag-discuss">议</span></h2>
|
||||
<p><small>今天上午没有编码练习——先把协作流程和项目方向定下来,Day6–10
|
||||
的项目实作会真的用到今天讨论的结论。</small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="task-card">
|
||||
<h4>任务卡 1 · 逐一验证 <span class="tag tag-practice">练</span></h4>
|
||||
<p>从 <code class="filelink">p01/ch03</code> 挑 8–10 个文件(namespace / reference /
|
||||
overload / const 系列),逐个执行:</p>
|
||||
<pre><code class="bash" data-trim>tools/run.sh p1c03_03 # namespace_syntax
|
||||
tools/run.sh p1c03_33 # reference_essence
|
||||
tools/run.sh p1c03_43 # function_overload_basics_2
|
||||
# ……自行在 build/ 里用 ninja -t targets 或 cmake --build 找到其余目标名</code></pre>
|
||||
<p>对照 <code class="filelink">docs/ERRATA.md</code> 对应条目,写一句话解释
|
||||
「wiki 原文错在哪、现在为什么对」。</p>
|
||||
<div class="task-card discuss-card">
|
||||
<h4>任务卡 1 · 协作分工 <span class="tag tag-discuss">议</span></h4>
|
||||
<dl class="task-spec">
|
||||
<dt>目标</dt>
|
||||
<dd>结合服务流程图,说清楚本组打算怎么分工使用 Jira(任务跟踪)+ Git(代码版本管理)</dd>
|
||||
<dt>验收标准</dt>
|
||||
<dd>每组提交一句话分工说明(谁负责建 Jira 看板 / 谁负责 Git 仓库初始化),能在图上指出对应环节</dd>
|
||||
<dt>基础知识 · 参考</dt>
|
||||
<dd>上一节"实习实训服务流程"图 ·
|
||||
<a class="filelink" target="_blank" href="../../TRAINING_PLAN_2026.md">TRAINING_PLAN_2026.md 「七、质量保证 (一)(二)」</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="task-card">
|
||||
<h4>任务卡 2 · 版本探针实操 <span class="tag tag-practice">练</span></h4>
|
||||
<pre><code class="bash" data-trim>tools/std_probe.py --lang c --file p01/ch03/ternary_operator.c \
|
||||
--standards c89,c99,c11,c17 --pedantic-errors</code></pre>
|
||||
<p>记录哪个标准报错、哪个不报错,对照
|
||||
<code class="filelink">docs/VERSION_NOTES.md §2</code> 的结论,理解“同一段代码
|
||||
在不同标准下含义不同”。</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="task-card">
|
||||
<h4>任务卡 3 · 拔高(选做) <span class="tag tag-practice">练</span></h4>
|
||||
<p>阅读 <code class="filelink">docs/ERRATA.md [58954439:42]</code>,解释生成脚本的
|
||||
去重逻辑为什么会把重载函数改名导致二义性——这是一次「工具误伤正确代码」的真实案例,
|
||||
训练读 diff、读生成器逻辑的能力。</p>
|
||||
<p><small>参考:<a class="filelink" target="_blank"
|
||||
href="../../../tools/gen_part1.py">tools/gen_part1.py</a> 中 <code>dedupe</code> 相关逻辑</small></p>
|
||||
<div class="task-card discuss-card">
|
||||
<h4>任务卡 2 · 选定项目方向 <span class="tag tag-discuss">议</span></h4>
|
||||
<dl class="task-spec">
|
||||
<dt>目标</dt>
|
||||
<dd>选定实训期间打算做的项目方向(Linux C 方向,或 C++/Qt 方向的备选商业项目之一)</dd>
|
||||
<dt>验收标准</dt>
|
||||
<dd>每组报出项目名称 + 一句话说明选择理由</dd>
|
||||
<dt>基础知识 · 参考</dt>
|
||||
<dd><a class="filelink" target="_blank" href="../../TRAINING_PLAN_2026.md">TRAINING_PLAN_2026.md 「八、备选商业项目介绍」</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@@ -177,107 +104,74 @@ tools/run.sh p1c03_43 # function_overload_basics_2
|
||||
<!-- ===================== 模块 B:讲 ===================== -->
|
||||
<section>
|
||||
<section>
|
||||
<p class="module-badge">模块 B · 讲授 35min</p>
|
||||
<h2>类和对象基础 <span class="tag tag-lecture">讲</span></h2>
|
||||
<ul>
|
||||
<li>封装:C 结构体 vs C++ 类</li>
|
||||
<li>构造 / 析构的调用时机</li>
|
||||
<li>深拷贝 vs 浅拷贝</li>
|
||||
<li>静态成员与单例</li>
|
||||
</ul>
|
||||
<p class="module-badge">模块 B · 讲授 35min(巡礼式,压缩讲解)</p>
|
||||
<h2>C++ 回顾 / CMake / Vcpkg <span class="tag tag-lecture">讲</span></h2>
|
||||
<p><small>只挑「学过但容易讲不透」的点,不逐章展开——方案书官方定位是
|
||||
"回顾和提升",深度让位于 Day2–5 的 Qt 内容。</small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>封装:同一个问题,两种语言写法 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="c" data-trim data-noescape>
|
||||
// C:结构体没有访问控制,甚至类型都保护不了
|
||||
typedef struct _Person{ char name[64]; int age; } Person;
|
||||
typedef struct _Aninal{ char name[64]; int age; int type; } Ainmal;
|
||||
|
||||
void AnimalEat(Ainmal* animal){ printf("%s在吃动物吃的饭!\n", animal->name); }
|
||||
|
||||
int main(){
|
||||
Person person; strcpy(person.name, "小明"); person.age = 30;
|
||||
AnimalEat(&person); // 把 Person* 传给期望 Ainmal* 的函数——编译器毫无察觉
|
||||
}
|
||||
</code></pre>
|
||||
<p><small>对照:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s01/class_encapsulation.c">class_encapsulation.c</a> vs
|
||||
<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s01/class_encapsulation.cpp">class_encapsulation.cpp</a>
|
||||
(public/protected/private 三级访问控制)</small></p>
|
||||
<h3>namespace 作用域 <span class="tag tag-lecture">讲</span></h3>
|
||||
<p>"作用域"不是"文件顺序"——很多人误以为 namespace 只是给名字加前缀,
|
||||
实际上它定义的是一段可以被跨文件延续、跨块合并的作用域。</p>
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/namespace_syntax.cpp">p01/ch03/namespace_syntax.cpp</a>,
|
||||
对照 <a class="filelink" target="_blank" href="../../ERRATA.md">docs/ERRATA.md</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>构造 / 析构的调用时机 <span class="tag tag-lecture">讲</span></h3>
|
||||
<h3>函数重载决议 <span class="tag tag-lecture">讲</span></h3>
|
||||
<p>编译器靠"名字改写"(name mangling)把重载函数变成不同的符号;二义性
|
||||
往往不是代码写错了,而是重载集合里存在两个"一样好"的候选。</p>
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/function_overload_mechanism.cpp">p01/ch03/function_overload_mechanism.cpp</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>引用的本质 <span class="tag tag-lecture">讲</span></h3>
|
||||
<p>把引用理解成"自动解引用的 const 指针"——这个实现视角能解释引用为什么
|
||||
必须初始化、为什么不能重新绑定。</p>
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch03/reference_essence.cpp">p01/ch03/reference_essence.cpp</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>虚析构与内存泄漏 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
class Person{
|
||||
public:
|
||||
Person(){
|
||||
cout << "构造函数调用!" << endl;
|
||||
pName = (char*)malloc(sizeof("John"));
|
||||
strcpy(pName, "John");
|
||||
}
|
||||
~Person(){
|
||||
cout << "析构函数调用!" << endl;
|
||||
if (pName != NULL){ free(pName); pName = NULL; }
|
||||
}
|
||||
private:
|
||||
char* pName;
|
||||
};
|
||||
</code></pre>
|
||||
<p><small>强化点:wiki 原文这一串例子普遍漏写 <code>#include <cstring></code>
|
||||
(用到 strcpy 却不声明)——出处 <a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s03/ctor_and_dtor.cpp">p01/ch04/s03/ctor_and_dtor.cpp</a>,
|
||||
<code class="filelink">ERRATA.md [58954451:0..13] missing-include</code>:编译器不报错,
|
||||
但换个平台/换个头文件包含顺序就可能炸——这类隐式依赖正是“强化”该抓的细节。</small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>深拷贝 vs 浅拷贝 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
class Person{
|
||||
public:
|
||||
Person(char* name, int age){
|
||||
pName = (char*)malloc(strlen(name) + 1);
|
||||
strcpy(pName, name);
|
||||
}
|
||||
// 自己实现拷贝构造函数 —— 深拷贝
|
||||
Person(const Person& person){
|
||||
pName = (char*)malloc(strlen(person.pName) + 1);
|
||||
strcpy(pName, person.pName);
|
||||
}
|
||||
~Person(){ if (pName != NULL) free(pName); }
|
||||
private:
|
||||
char* pName;
|
||||
};
|
||||
void test(){
|
||||
Person p1("Edward", 30);
|
||||
Person p2 = p1; // 不写拷贝构造 → 默认浅拷贝 → 两个指针指向同一块内存 → 析构两次 double free
|
||||
}
|
||||
Base* p = new Derived();
|
||||
delete p; // 如果 ~Base() 不是 virtual,~Derived() 不会被调用——经典泄漏
|
||||
</code></pre>
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s03/deep_vs_shallow_copy.cpp">p01/ch04/s03/deep_vs_shallow_copy.cpp</a></small></p>
|
||||
href="../../../p01/ch04/s08/virtual_dtor_purpose.cpp">p01/ch04/s08/virtual_dtor_purpose.cpp</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>静态成员与单例 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="cpp" data-trim data-noescape>
|
||||
class Printer{
|
||||
public:
|
||||
static Printer* getInstance(){ return pPrinter; }
|
||||
void PrintText(string text){ cout << text << endl; mTimes++; }
|
||||
private:
|
||||
Printer(){ mTimes = 0; }
|
||||
Printer(const Printer&){} // 禁止拷贝
|
||||
private:
|
||||
static Printer* pPrinter;
|
||||
int mTimes;
|
||||
};
|
||||
Printer* Printer::pPrinter = new Printer; // 类外初始化静态成员
|
||||
</code></pre>
|
||||
<h3>模板与 STL 速览 <span class="tag tag-lecture">讲</span></h3>
|
||||
<p>只点名,不展开:泛型编程(函数模板/类模板)+ 容器/迭代器,是 Day6–10
|
||||
项目实作里会大量用到的基础设施。</p>
|
||||
<p><small>出处:<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s03/static_singleton.cpp">p01/ch04/s03/static_singleton.cpp</a></small></p>
|
||||
href="../../../p01/ch05/class_template_basics.cpp">p01/ch05/class_template_basics.cpp</a>、
|
||||
<a class="filelink" target="_blank" href="../../../p01/ch09/s03/vector_iterator.cpp">p01/ch09/s03/vector_iterator.cpp</a></small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>CMake:用本仓库当教材 <span class="tag tag-lecture">讲</span></h3>
|
||||
<pre><code class="bash" data-trim>cmake -S . -B build -G Ninja -DBUILD_QT_PART=OFF -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build # 144 个目标全绿</code></pre>
|
||||
<p><small>出处:仓库根 <a class="filelink" target="_blank" href="../../../CMakeLists.txt">CMakeLists.txt</a>——
|
||||
<code>option(BUILD_QT_PART)</code> 控制是否编译 Qt 部分,每个示例一个
|
||||
<code>add_executable</code> 目标,这就是"一文件一目标"约定的由来。</small></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Vcpkg 包管理器(概念,无演示) <span class="tag tag-lecture">讲</span></h3>
|
||||
<p>C++ 生态的包管理器,解决"第三方库怎么装、怎么被 CMake 找到"的问题。</p>
|
||||
<div class="verify-box">
|
||||
<h4>缺口说明</h4>
|
||||
<p>本仓库用的是"隔离 Qt 手动装"(<code>tools/install_qt_host.sh</code>)
|
||||
而非 vcpkg,两种思路都要认识;本仓库暂无 vcpkg 可运行示例——安装真实
|
||||
vcpkg 工具链超出最小示例范畴,此处仅作概念介绍。</p>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -285,37 +179,50 @@ Printer* Printer::pPrinter = new Printer; // 类外初始化静态成员
|
||||
<section>
|
||||
<section>
|
||||
<p class="module-badge">模块 B · 练习 95min</p>
|
||||
<h2>动手:类和对象 <span class="tag tag-practice">练</span></h2>
|
||||
<h2>动手:走一遍真实构建流程 <span class="tag tag-practice">练</span></h2>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="task-card">
|
||||
<h4>任务卡 1 · 扩展一个类 <span class="tag tag-practice">练</span></h4>
|
||||
<p>以 <a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s02/point_and_circle.cpp">point_and_circle.cpp</a> 或
|
||||
<a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s02/cube_class_design.cpp">cube_class_design.cpp</a> 为起点,
|
||||
新增一个成员函数(如计算面积 / 体积),编译运行验证输出正确。</p>
|
||||
<h4>任务卡 1 · 走一遍真实构建流程 <span class="tag tag-practice">练</span></h4>
|
||||
<dl class="task-spec">
|
||||
<dt>目标</dt>
|
||||
<dd>独立完成本仓库 Part1 的配置+构建,不看着教师操作</dd>
|
||||
<dt>验收标准</dt>
|
||||
<dd><code>cmake -S . -B build -G Ninja -DBUILD_QT_PART=OFF</code> 配置成功;
|
||||
<code>cmake --build build</code> 144 个目标全绿;能说出 <code>option(BUILD_QT_PART)</code> 的作用</dd>
|
||||
<dt>基础知识 · 参考</dt>
|
||||
<dd><a class="filelink" target="_blank" href="../../../CMakeLists.txt">仓库根 CMakeLists.txt</a> ·
|
||||
<span class="ext-ref">CMake 官方文档 Tutorial(选读·需联网)</span></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="task-card">
|
||||
<h4>任务卡 2 · 复现并修复浅拷贝崩溃 <span class="tag tag-practice">练</span></h4>
|
||||
<p>修改 <a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s03/deep_vs_shallow_copy.cpp">deep_vs_shallow_copy.cpp</a>:
|
||||
故意删掉拷贝构造函数触发浅拷贝,用 <code class="filelink">tools/run.sh</code>
|
||||
观察 double free / 崩溃或异常输出,再恢复深拷贝对比。</p>
|
||||
<h4>任务卡 2 · 修一个真实的坑 <span class="tag tag-practice">练</span></h4>
|
||||
<dl class="task-spec">
|
||||
<dt>目标</dt>
|
||||
<dd>从 <a class="filelink" target="_blank" href="../../ERRATA.md">docs/ERRATA.md</a>
|
||||
挑 2 条记录,理解"wiki 原文错在哪、现在的写法为什么对"</dd>
|
||||
<dt>验收标准</dt>
|
||||
<dd>能用一句话向同组同学解释清楚,不能只念代码</dd>
|
||||
<dt>基础知识 · 参考</dt>
|
||||
<dd><a class="filelink" target="_blank" href="../../ERRATA.md">docs/ERRATA.md</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="task-card">
|
||||
<h4>任务卡 3 · 独立实现单例 <span class="tag tag-practice">练</span></h4>
|
||||
<p>参照 <a class="filelink" target="_blank"
|
||||
href="../../../p01/ch04/s03/static_singleton.cpp">static_singleton.cpp</a>,
|
||||
独立写一个单例类(拷贝构造设为私有 / delete,验证多次 <code>getInstance()</code>
|
||||
返回同一地址)。</p>
|
||||
<h4>任务卡 3(选做)· 版本探针 <span class="tag tag-practice">练</span></h4>
|
||||
<dl class="task-spec">
|
||||
<dt>目标</dt>
|
||||
<dd>用 <code>tools/std_probe.py</code> 验证一个标准版本差异点(如三目运算符可否作左值)</dd>
|
||||
<dt>验收标准</dt>
|
||||
<dd>跑出至少一个"该标准报错、另一个标准不报错"的对比结果,对照
|
||||
<a class="filelink" target="_blank" href="../../VERSION_NOTES.md">docs/VERSION_NOTES.md</a> §2</dd>
|
||||
<dt>基础知识 · 参考</dt>
|
||||
<dd><a class="filelink" target="_blank" href="../../../tools/std_probe.py">tools/std_probe.py</a> ·
|
||||
<a class="filelink" target="_blank" href="../../VERSION_NOTES.md">docs/VERSION_NOTES.md</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@@ -324,14 +231,13 @@ Printer* Printer::pPrinter = new Printer; // 类外初始化静态成员
|
||||
<section>
|
||||
<h2>当日产出验证</h2>
|
||||
<div class="verify-box">
|
||||
<h4>验收标准</h4>
|
||||
<pre><code class="bash" data-trim>cmake --build build --target all_p01_ch03
|
||||
cmake --build build --target all_p01_ch04_s03</code></pre>
|
||||
<p>全绿;至少完成 1 个「浅拷贝崩溃复现 + 修复对比」。</p>
|
||||
<h4>验收</h4>
|
||||
<pre><code class="bash" data-trim>cmake --build build --target all # Part1,144 个目标全绿</code></pre>
|
||||
<p>每组提交一句话分工说明 + 至少 1 条 ERRATA 坑点讲解。</p>
|
||||
</div>
|
||||
<p class="footer-note"><small>明日预告:Day 2 —— OOP 进阶(对象模型 / 友元 /
|
||||
运算符重载 / 继承 / 多态)</small></p>
|
||||
<p><a class="filelink" href="index.html">返回目录</a></p>
|
||||
<p class="footer-note"><small>明天 Day2 进入 Qt:项目结构 / 信号槽 / 控件 / 布局与 QSS ——
|
||||
大纲:<a class="filelink" href="../OUTLINE.md">docs/teaching/OUTLINE.md</a></small></p>
|
||||
<p><a class="filelink" href="index.html">返回目录</a> · <a class="filelink" href="day2.html">下一天 →</a></p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@@ -341,11 +247,7 @@ cmake --build build --target all_p01_ch04_s03</code></pre>
|
||||
<script src="reveal/plugin/highlight/highlight.js"></script>
|
||||
<script>
|
||||
Reveal.initialize({
|
||||
hash: true,
|
||||
controls: true,
|
||||
progress: true,
|
||||
center: true,
|
||||
slideNumber: true,
|
||||
hash: true, controls: true, progress: true, center: true, slideNumber: true,
|
||||
plugins: [ RevealHighlight ]
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user