const对象只能调用const成员函数,否则编译器报错“passing ‘const x’ as ‘this’ argument discards qualifiers”,本质是禁止将只读对象当可修改对象使用;const成员函数内不可修改非mutable成员、不可调用非const成员函数、不可返回非常量引用,但可读取成员和调用const函数。

const 对象只能调用 const 成员函数,否则编译器直接拒绝 —— 这不是 bug,是 C++ 类型系统对“只读语义”的强制保障。
error: passing ‘const X’ as ‘this’ argument discards qualifiers 是什么
这是最常见的报错信息,本质是:你用一个 const X 类型的对象,去调用了声明为 X::func()(没加 const)的成员函数。编译器发现,这个函数签名承诺“可能修改 *this”,但你传入的是“保证不被修改”的对象,于是判定权限违规(把 const 对象当非 const 用,属于权限放大)。
常见触发场景:
- 定义了
const Person p;,然后写p.setName("Alice");,而setName没加const - 在 const 成员函数里调用了另一个没加
const的成员函数,比如this->helper(); - 容器成员是
std::vector<int> data;</int>,你在 const 函数里写了data.begin()—— 此时data被视为 const,调用的是vector::begin() const,返回const_iterator;若你把它赋给auto it = data.begin();再试图*it = 42;,后续操作会失败
为什么普通对象能调用 const 成员函数,反过来不行
因为权限可以缩小,不能放大。
Person p; 是非 const 对象,this 类型是 Person*;调用 void show() const 时,this 在函数内变成 const Person* —— 这是安全的收缩。
但 const Person p; 的 this 天然是 const Person*,若允许它调用 void setAge(int)(其 this 是 Person*),就等于把只读对象“降级”成可写,破坏 const 正确性。
所以规则很硬:
-
const X对象 → 只能调用X::f() const -
X对象 → 可以调用X::f()和X::f() const
const 成员函数里到底不能干什么
它锁住的是 *this 的可修改性,不是函数体内所有变量。具体禁止行为包括:
- 给非
mutable的非静态成员变量赋值,例如age = 30;→ 报错assignment of member 'X::age' in read-only object - 调用非 const 成员函数,例如
validate();(而validate()没加const)→ 报错passing 'const X' as 'this' argument discards qualifiers - 返回成员变量的非常量引用,例如
int& getAge() { return age; }在 const 函数里调用 → 编译失败,因为会暴露可写入口 - 调用
operator=、push_back等明显会修改对象状态的函数
但允许的操作有:
- 读取任何成员(
cout ) - 修改
mutable成员(如缓存计数器mutable int cache_hits_;) - 调用其他 const 成员函数
- 修改局部变量、参数、全局变量、静态成员变量(如
static int total;)
声明和定义分离时 const 容易漏掉的地方
const 是函数类型的一部分,声明和定义必须完全一致,否则编译器认为是两个不同函数,导致链接失败或静默调用错误版本。
头文件中写:
class X {
public:
int value() const;
};
实现文件中必须写:
int X::value() const {
return val_;
}
常见错误:
- 头文件写了
const,实现文件漏了 → 链接时报undefined reference to X::value() const - 实现文件多写了
&或&&,比如int X::value() const &→ 类型不匹配,除非声明也带引用限定符 - 把
const错放在返回类型前:const int value();→ 这只是返回 const int,跟 const 成员函数无关
真正容易被忽略的点是:哪怕函数看起来“只是读”,只要它调用了任何非 const 成员(包括隐式调用,比如 std::string::c_str() 在旧标准里是非 const 的),就必须确保整条调用链上的每个成员函数都标记为 const。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











