🔷 第二章 C++语言基础
📄 一句话概括

前面的常量都是"直接写出来的值",这一节讲给常量起名字——符号常量。两种做法:const(const double PI = 3.14159;,有类型、编译器帮你检查,推荐)和 #define(#define PI 3.14159,本质是预处理阶段的文本替换,没有类型,老代码里常见)。另外还有布尔常量 true / false——看着是"真/假",存进去就是 1 和 0。

一、符号常量:为什么给常量起名字

cout << 3.14159 * r * r << endl;      // 这个 3.14159 是什么?

代码里突然冒出一个数字(行话叫魔法数字),三个月后连你自己都不知道它是干嘛的。改成:

const double PI = 3.14159;
cout << PI * r * r << endl;           // 一眼看懂:圆的面积

三个好处:

  1. 自解释:名字说明含义
  2. 一改全改:税率从 0.13 变 0.09,只改定义那一行
  3. 防手误:不用在十几个地方各敲一遍 3.14159

二、两种做法对比

做法一:const(推荐)

const double PI = 3.14159;     // 定义时必须给值
const int MAX_SIZE = 100;

PI = 3.14;                     // ✗ 报错:不能给常量赋值

做法二:#define(预处理宏)

#define PI 3.14159             // 注意:末尾不加分号,也不写 =
#define MAX_SIZE 100

cout << PI << endl;            // 编译前 PI 已被换成 3.14159
const #define
谁处理 编译器 预处理器(编译之前)
有类型吗 有 没有
检查严格吗 严格 不检查
能调试吗 能(看得到名字) 看不到(早被替换)
结尾 要分号 不要分号
建议 优先用这个 认识它、读得懂老代码即可

命名习惯:符号常量习惯全大写(PI、MAX_SIZE、TAX_RATE),一眼和普通变量区分开。

三、布尔常量

bool isOk = true;       // 真
bool isDone = false;    // 假

小知识:C 语言里原本没有 true/false(只有 1 和 0),是 C++ 引入的。所以在看 C 的老代码时,看到 if (flag == 1) 别奇怪。

四、动手 Demo:三个实验看清 const 与 #define 的区别

新建 constdemo.cpp:

#include <iostream>
using namespace std;

#define MAX_SIZE 100          // 宏常量:不加分号

int main() {
    const double PI = 3.14159;   // const 常量:要加分号

    cout << "PI = " << PI << endl;
    cout << "MAX_SIZE = " << MAX_SIZE << endl;

    // PI = 3.14;                // ← 打开这行试试
    return 0;
}

实验一:把 PI = 3.14; 那行的注释打开,编译。 → 预期报错类似 assignment of read-only variable 'PI'——"read-only"就是"只读",即常量不许改。

实验二:给 #define MAX_SIZE 100 末尾加一个分号,编译。 → 观察报错或警告(有的编译器能过,有的会报奇怪错误)。这个实验告诉你:宏后面那个分号会一起被替换进去。

实验三:把 #define MAX_SIZE 100 改成 #define MAX_SIZE "一百",再 cout << MAX_SIZE;。 → 竟然能输出 一百!因为 #define 只是文本替换,它根本不管"100 应该是数字"。这就是"没有类型检查"的真相。

看到什么算成功:三个实验都能说出"为什么会这样"。

30 秒实验:把 cout << true << " " << false << endl; 加进去,看输出是不是 1 0。

五、常见误区

  1. "const 和 #define 差不多,用哪个都行"——差得多。#define 没有类型检查,出错时报错信息会指向被替换后的怪代码,非常难查。新代码一律优先 const
  2. "#define 后面要加分号"——不要。加了分号,分号也会被一起替换进去,可能引发莫名其妙的错误
  3. "const 常量可以先定义后赋值"——不行。定义时必须给初始值:const int A; 会报错
  4. "true、false 是普通变量名"——它们是关键字,不能当变量名(int true = 1; 直接报错)
自测四问(点开对答案) 1. `const` 和 `#define` 的本质区别?——`const` 由**编译器**处理、**有类型**、会做检查;`#define` 由**预处理器**做**纯文本替换**、没有类型、不检查。 2. 为什么优先用 `const`?——有类型、能调试、报错清楚、有作用域;`#define` 出错时定位困难。 3. `#define` 末尾能不能加分号?——**不能**,分号会跟着被替换进去,可能引发错误。 4. 布尔常量 `true` / `false` 在内存里是什么?——**1 和 0**(`cout << true` 输出 1)。

相关笔记