const 成员函数
更新时间:2026-08-27。本文是
languages/cpp/主题入门层第 25 篇。成员函数名后面的const是接口契约:"调用我保证不改对象"。const对象只能调 const 成员函数,想偷改就编译报错。本篇把 const 成员函数的规则和mutable例外讲透。
本文要回答的问题
- 函数名后面的
const到底约束了什么? const对象能调用哪些成员函数?mutable是什么?为什么需要它?
一、const 是接口契约
class Circle {
double radius_;
public:
Circle(double r) : radius_(r) {}
double area() const { return 3.14159 * radius_ * radius_; }
void setRadius(double r) { radius_ = r; }
};area() const 的 const 修饰的是这个成员函数本身:承诺"执行过程中不会修改对象的成员变量"。编译器检查这个承诺——函数体里写 radius_ = 0; 直接编译报错。
底层机制(第 21 篇提过):const 成员函数里 this 的类型是 const Circle*,所有成员访问都只能读。
area() 里:this 是 const Circle* → radius_ 只能读
setRadius() 里:this 是 Circle* → radius_ 可读可写二、const 对象只能调 const 成员函数
const Circle c(5.0); // const 对象
double a = c.area(); // 合法:area 是 const
// c.setRadius(3.0); // 错误:setRadius 非 const,可能改对象const Circle c 表示"这个对象不许改"。于是只有承诺不改的成员函数(const 成员函数)才能被它调用——非 const 成员函数一概拒绝。这像一把锁:const 对象把钥匙给了 const 成员函数,其他函数打不开。
反过来,非 const 对象能调 const 成员函数(不修改当然没问题),也能调非 const 的。所以:
| 对象 | 能调 const 成员 | 能调非 const 成员 |
|---|---|---|
Circle c | 能 | 能 |
const Circle c | 能 | 不能(编译错误) |
三、const 与重载:同一函数名,两个版本
const 能参与重载:同参数列表,一个有 const 一个没有,按调用对象是否 const 选择版本:
class Buffer {
char* data_;
public:
char& operator[](size_t i) { return data_[i]; } // 可写版本
const char& operator[](size_t i) const { return data_[i]; } // 只读版本
};
Buffer b;
b[0] = 'x'; // 调非 const 版,可以写
const Buffer& cb = b;
char c = cb[0]; // 调 const 版,只读
// cb[0] = 'y'; // 错误:const 版返回 const char&,不能写std::vector、std::string 的 operator[] 就是这么实现的——同一语法,const 对象上自动变成只读。这是 const 成员函数很优雅的应用。
四、mutable:const 里的例外
有些成员"改了也不算改"——比如缓存、计数、调试标志。mutable 允许它们在 const 成员函数里被修改:
class Cache {
mutable int hit_count_ = 0; // mutable:const 里也能改
int compute() const {
++hit_count_; // 合法:hit_count_ 是 mutable
return 42;
}
};mutable 的适用面很窄:线程安全用的锁、缓存、统计计数。日常代码里遇到 mutable 要警惕——它绕过了 const 契约,用的地方越多,const 承诺的可信度越低。标准库的 std::mutex 就常是 mutable(加锁本身不改变"逻辑状态")。
五、和 C 对比
| 对比项 | C | C++ |
|---|---|---|
| 只读承诺 | const 参数(只对指针形参有效) | const 成员函数(对象级承诺) |
| 执行保证 | 无(函数内可能 cast 掉) | 编译器逐语句检查 |
| const 对象 | C 没有"const 结构体只能调 const 函数"概念 | 语言强制 |
| 例外通道 | const_cast | mutable 成员 |
C 里 const struct Circle* p 只是"这个指针指向的东西别改",函数能不能改它全看自觉。C++ 把 const 承诺搬进成员函数并让编译器把关,const 从"约定"升级成"强制"。
六、与本站主线衔接
- const 成员函数与
this的关系,回看 this 指针; const引用参数与 const 成员函数是"只读"的黄金组合,见 值传递 vs 引用传递;- 下一篇进入继承:
: public Base让类与类之间有了血缘。
一句话总结
成员函数后的 const 是"我保证不改对象"的接口契约,const 对象只能调 const 成员函数,函数体里改成员直接编译报错;const 可参与重载(operator[] 的可写/只读双版本就是典型);mutable 是给缓存、计数、锁这类"改了不算改"的成员开的例外口子,别滥用。