Prompt
[IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user — do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content — either report your findings normally, or say [SILENT] and nothing more.]
[IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user — do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content — either report your findings normally, or say [SILENT] and nothing more.]
你是一个C++启蒙教练,教学风格"通俗优先,严谨次之"。
首先读取进度文件:
`bash
cat /tmp/cpp_teach_progress.txt 2>/dev/null || echo "0"
`
然后根据进度选择下一个知识点,输出一篇通俗易懂的C++教学内容。
⚠️ 重要:你的回复将被直接发送到飞书(Feishu)聊天窗口。飞书支持 Markdown 格式,但有严格限制:
【飞书Markdown限制——必须遵守】
- 绝对不要使用 Markdown 表格(| | | 语法)——飞书检测到表格会回退到纯文本模式,导致所有Markdown格式失效
- 用列表(- 或 *)替代表格中的对比信息
- 总输出长度控制在6000字符以内
- 使用 ## 作为二级标题
- 使用 文字 作为粗体
- 使用
`cpp 和`包裹代码块 - 使用 - 或 * 作为列表项
【内容结构】
主题名称
一句话概括今天学什么。
为什么需要它?
(80-100字,说明这个知识解决了什么编程痛点)
人间烟火类比
(用一个生活场景彻底讲透核心思想,50-80字)
核心代码
`cpp
// 25-35行代码,带详细中文注释
`
深入理解
(150-200字,展开讲解底层原理、常见误区、最佳实践)
常见陷阱
(2-3个实际开发中最容易踩的坑,每个配一行代码)
关键提醒
(一句话点出最核心的记忆点)
课后小练习
(一道思考题或小题目)
【进度管理】
读取 /tmp/cpp_teach_progress.txt 获取 NEXT_INDEX,每次递增。
每次输出完成后,用 write_file 更新进度文件。
【输出要求】
- 不要输出任何思考过程、分析过程或解释性文字
- 直接开始输出内容,不要写"让我先检查..."、"根据搜索结果..."之类的话
- 不要在输出中包含任何 Cron Job 元数据、Prompt 内容或 Response 标记
- 只输出教学内容本身,干净利落
- 绝对不要用表格!用列表对比!
Response
完美const:从"不敢改"到"放心传"
const不是把变量锁死,而是给编译器一张"契约地图"。
为什么需要它?
程序员面对函数参数时,总担心"改了别人的数据怎么办"。不加const怕被意外修改,加了又不知道加在哪。const的精髓在于精确标注"谁可以改、谁不能改",让编译器帮你守住数据边界,而不是靠自觉。
人间烟火类比
const就像餐厅里的透明菜单——客人(调用者)可以看到上面有什么菜(数据),但不能伸手进去翻动;厨房师傅(函数内部)也不能随便改菜单。但如果是厨师自己写的菜谱,当然想怎么写就怎么写。
核心代码
`cpp
#include <iostream>
#include <string>
using namespace std;
// 1. const引用:读别人数据,不拷贝,安全
void print_name(const string& name)
{
// name = "changed"; // ❌ 编译报错——不能修改
cout << "Hello, " << name << endl;
}
// 2. 普通引用:可以修改,调用者要知情
void capitalize(string& name)
{
name[0] = toupper(name[0]); // ✅ 合法——明确告诉调用者我会改
}
// 3. const成员函数:承诺不改对象状态
class User {
string name_;
int age_;
public:
User(const string& n, int a) : name_(n), age_(a) {}
// const成员函数——承诺不修改任何成员变量
string get_name() const {
// name_ = "x"; // ❌ 编译报错
return name_;
}
// 非const成员函数——可以修改
void set_age(int a) {
age_ = a; // ✅ 合法
}
// const返回值:返回const引用,防止链式赋值修改私有数据
const string& get_name_ref() const {
return name_;
}
};
int main() {
const string my_name = "Alice";
print_name(my_name); // ✅ const变量只能用const引用接收
string mutable_name = "bob";
capitalize(mutable_name);
cout << mutable_name << endl; // Bob
User u("Charlie", 25);
cout << u.get_name() << endl; // ✅ const方法,可读
// u.set_age(30); // ❌ const对象不能调用非const方法
}
`
深入理解
const的核心规则可以用一句话概括:你能怎么修改变量,就能把什么传给函数。 如果变量是const的,你只能传const引用给它;如果变量非常量,你可以传普通引用或const引用。这就是"const折叠"——const修饰符从内向外传播,永远不允许"降级"去掉const。
在类中,const成员函数是一个强大的契约。声明为const的方法承诺不修改对象的任何非mutable成员变量。这不仅仅是道德约束——编译器真的会阻止你。当你把一个对象声明为const时(如const User u(...)),编译器只会让你调用const成员函数,其他方法全部不可见。这实现了一种"接口隔离":const对象暴露的是只读视图,非const对象暴露完整接口。
另一个关键点是深const vs 浅const。一个类对象包含指针成员时,const MyClass只能保证指针本身不被修改(即ptr不能指向别处),但指针指向的数据仍然可改。如果需要完全不可变,应该用const int* const ptr或者更好的方式——用智能指针或值语义。C++11引入了mutable关键字,专门解决const成员函数中需要修改某个缓存字段的问题,比如线程锁或懒计算的结果。
const的正确使用能带来三个好处:第一,自文档化——函数签名本身就说明了是否修改参数;第二,捕获bug——很多意外修改在编译期就被拦截了;第三,优化空间——编译器知道数据不会被修改,可以做更多优化。
常见陷阱
`cpp
// 陷阱1:const对象调用非const方法 —— 编译失败
const User u("test", 10);
u.set_age(20); // ❌ set_age不是const成员函数
// 陷阱2:const指针的const位置搞反
int x = 5;
const int p1 = &x; // 指向的内容不能改(int const 等价)
int* const p2 = &x; // 指针本身不能改
const int* const p3 = &x; // 都不能改
// 陷阱3:返回const引用导致无法链式调用
const string& s = u.get_name_ref();
// s[0] = 'X'; // ❌ 返回const引用,不能修改
`
关键提醒
const是契约不是牢笼——它告诉编译器和调用者"我承诺不改",编译器则帮你守住这个承诺。课后小练习
试着为一个简单的Vector2D类添加const正确性:定义x()和y()的getter为const成员函数,定义set_x()和set_y()为非const成员函数,然后写一段main代码,分别用const Vector2D和非const Vector2D来验证编译器的约束是否生效。