问题背景
编译下面这段代码时遇到了报错:
bash
ubuntu@:~///$ g++ zzx_const.cpp
zzx_const.cpp: In function 'void printPerson(const Person&)':
zzx_const.cpp:34:14: error: passing 'const Person' as 'this' argument discards qualifiers [-fpermissive]
34 | p.setName("test"); // 不能调用非 const 函数
| ~~~~~~~~~^~~~~~~~
zzx_const.cpp:21:10: note: in call to 'void Person::setName(const string&)'
21 | void setName(const std::string& n)
| ^~~~~~~
疑问: 报错信息里的 qualifiers 是不是"限定符、修饰符"的意思
解答
可以翻译为**"限定符"。在 C++ 中,它专指 类型限定符**,也叫 cv 限定符(cv-qualifiers),只有两个:
constvolatile
因此 discards qualifiers 的意思是"丢弃了限定符 ",在这个例子里丢掉的就是 const。
qualifier 与 specifier 的区别
"修饰符"这个词的范围比 qualifier 更宽,并不完全对应:
| 术语 | 中文 | 典型关键字 |
|---|---|---|
| qualifier | 限定符 | const、volatile |
| specifier | 说明符 | static、inline、virtual、explicit |
报错里出现 qualifiers 时,基本就是指 const 或 volatile。
补充:为什么报错里会出现 'this'
成员函数末尾的 const(如 getName() const)同样是 cv 限定符,它限定的是隐含的 this 指针,使 this 的类型变为 const Person*。
在本例中:
printPerson的参数是const Person&,所以p是 const 对象setName不是 const 成员函数,它的this类型是Person*- 用 const 对象调用非 const 成员函数,相当于把
const Person*转成Person*,丢掉了const,因此报错discards qualifiers
解决方法: 如果 setName 确实需要修改对象,就不要对 const 对象调用它;如果是只读函数(如 getName),则在函数末尾加上 const。