在 C++ 中,在成员函数声明后添加 const 关键字表示这是一个常量成员函数(const member function),这是 C++ 常量正确性的核心概念之一。
核心作用与意义
- 承诺不修改对象状态:
- 该函数不会修改调用它的对象的任何成员变量(除非成员变量被声明为
mutable) - 编译器会强制实施这一承诺
- 该函数不会修改调用它的对象的任何成员变量(除非成员变量被声明为
- 启用 const 对象调用:
- 允许被
const修饰的对象调用这些函数 - 非 const 成员函数无法被 const 对象调用
- 允许被
语法形式
代码语言:javascript
AI代码解释
class MyClass {
public:
// 常量成员函数
void display() const;
// 非常量成员函数
void modify();
};
底层原理
当成员函数被声明为 const 时:
- 编译器将
this指针类型从MyClass*变为const MyClass* - 函数内所有成员访问都视为通过
const指针访问
代码语言:javascript
AI代码解释
// 编译器视角的转换
void display(const MyClass* this); // const 版本
void modify(MyClass* this); // 非 const 版本
关键特性
1. 对象调用权限
|
对象类型 |
常量成员函数 |
非常量成员函数 |
|---|---|---|
|
const 对象 |
✅ 允许 |
❌ 禁止 |
|
非 const 对象 |
✅ 允许 |
✅ 允许 |
2. 成员访问限制
代码语言:javascript
AI代码解释
class Counter {
int count; // 普通成员
mutable int accessCount; // mutable 成员
public:
void increment() const {
// count++; // 错误!不能修改普通成员
accessCount++; // 允许:mutable 成员可修改
}
};
3. 函数重载
const 可参与函数重载,编译器根据对象的常量性选择版本:
代码语言:javascript
AI代码解释
class TextBuffer {
std::string text;
public:
// 非 const 版本
char& operator[](size_t pos) {
return text[pos]; // 返回可修改引用
}
// const 版本
const char& operator[](size_t pos) const {
return text[pos]; // 返回只读引用
}
};
// 使用场景
TextBuffer buffer;
buffer[0] = 'A'; // 调用非 const 版本
const TextBuffer cbuf;
char c = cbuf[0]; // 调用 const 版本
// cbuf[0] = 'B'; // 错误!尝试修改 const 对象
实际应用场景
场景 1:访问器方法(Getter)
代码语言:javascript
AI代码解释
class Person {
std::string name;
int age;
public:
// const Getter:安全访问成员
std::string getName() const { return name; }
int getAge() const { return age; }
};
void printPerson(const Person& p) {
// 可调用 const 方法
std::cout << p.getName() << ", " << p.getAge();
}
场景 2:接口设计
代码语言:javascript
AI代码解释
class Shape {
public:
// 纯虚 const 方法:强制派生类实现常量计算
virtual double area() const = 0;
};
class Circle : public Shape {
double radius;
public:
double area() const override {
return 3.14159 * radius * radius;
}
};
场景 3:STL 容器兼容
代码语言:javascript
AI代码解释
#include <vector>
void process(const std::vector<int>& vec) {
// 必须使用 const 版本的 begin/end
for (auto it = vec.begin(); it != vec.end(); ++it) {
// *it = 10; // 错误!迭代器是 const_iterator
}
}
进阶用法
1. 常量与非常量方法互调
代码语言:javascript
AI代码解释
class DataWrapper {
std::vector<int> data;
public:
// 非 const 版本调用 const 版本避免重复
const int& at(size_t pos) const {
// 复杂边界检查...
return data[pos];
}
int& at(size_t pos) {
// 使用 const_cast 移除常量性
return const_cast<int&>(
static_cast<const DataWrapper*>(this)->at(pos)
);
}
};
2. mutable 成员
代码语言:javascript
AI代码解释
class Cache {
mutable std::mutex mtx; // 可被 const 方法修改
mutable std::vector<int> cachedData;
mutable bool cacheValid = false;
public:
void updateCache() const {
std::lock_guard<std::mutex> lock(mtx);
if (!cacheValid) {
// 模拟耗时计算
cachedData = {1, 2, 3, 4, 5};
cacheValid = true;
}
}
};
3. 返回类型修饰
代码语言:javascript
AI代码解释
class Matrix {
double* data;
int rows, cols;
public:
// const 方法返回 const 指针
const double* rowData(int r) const {
return data + r * cols;
}
// 非 const 方法返回普通指针
double* rowData(int r) {
return data + r * cols;
}
};
最佳实践与陷阱
应遵循的原则
最小权限原则:
- 所有不修改对象状态的成员函数都应声明为
const - 默认使用 const 方法,除非确实需要修改状态
const 正确性传播:
代码语言:javascript
AI代码解释
class A {
B* b;
public:
// 正确:返回 const 指针
const B* getB() const { return b; }
// 错误:返回非 const 指针
// B* getB() const { return b; }
};
避免过度使用 mutable:
- 仅用于真正与对象逻辑状态无关的成员(如缓存、互斥锁)
常见错误
错误 1:修改成员变量
代码语言:javascript
AI代码解释
class Account {
double balance;
public:
void deductFee() const {
balance -= 5.0; // 错误!const 方法不能修改成员
}
};
错误 2:调用非 const 方法
代码语言:javascript
AI代码解释
class Logger {
std::vector<std::string> logs;
public:
void addLog(const std::string& msg) { logs.push_back(msg); }
void printAll() const {
for (const auto& log : logs) {
std::cout << log << "\n";
}
addLog("Printed"); // 错误!const 方法调用非 const 方法
}
};
错误 3:返回非 const 内部状态引用
代码语言:javascript
AI代码解释
class Config {
std::map<std::string, std::string> settings;
public:
// 危险:外部可通过引用修改内部状态
std::map<std::string, std::string>& getSettings() const {
return settings; // 错误!返回非 const 引用
}
};
性能影响
const 成员函数不会带来运行时性能开销:
- 纯粹是编译时检查机制
- 使编译器能进行更好的优化
- 提高代码可读性和安全性
关键总结:函数后的
const是 C++ 常量正确性的基石,它确保函数不修改对象状态,使 const 对象能安全调用方法,并通过重载提供更精确的接口设计。正确使用 const 成员函数能显著提高代码的健壮性和可维护性。

2048

被折叠的 条评论
为什么被折叠?



