const 修饰变量
面试官: 看到你的简历上写着熟悉 C++,那我们来聊聊 const 关键字吧。它在 C++ 中有很多用途。
我的第一个问题是: 当 const 用于修饰一个变量时,它意味着什么?它和 C 语言中的 #define 宏定义常量相比,有什么主要的优势?
| |
回答:
const关键字修饰变量,表示这个变量是一个常量,不能被修改。- 和
#define宏定义常量相比,const变量更加有下面的优势:- 类型检查:
const是有类型的变量,编译器会进行类型检查,而#define是纯文本变量,没有类型概念,容易引发隐性错误——编译通过但运行出错。 - 作用域控制:
const类型的变量可以定义在局部作用域中,而#define是全局替换,容易产生命名冲突 - 调试支持:
const变量可以在调试器中查看它的值和地址,而#define变量在预处理阶段就被替换到,调试器无法识别。 - 取地址操作:
const变量可以取地址,而#define是文本替换,没有地址的概念。 - 跨文件访问:
const变量可以通过extern声明在多个文件中共享,而#define无法跨文件共享,只能重新定义。
- 类型检查:
- 当然,
const最主要的优势还是类型检查和作用域控制。
const 与指针结合
面试官 (继续提问): 好的,你对 const 修饰普通变量的理解非常透彻。我们来看它和指针的结合。
请你解释一下,下面这三种声明中,p 的类型有什么不同?分别都约束了什么东西不能被修改?
| |
(提示:一个有用的技巧是“从右往左读”,或者看 const 在 * 的哪一边。)
回答:
- 第一种情况,
const int* p表示这是一个指向const int类型变量的指针,即指针所指的变量为常量,不能修改,但是指针值本身可以修改。 - 第二种情况,
int* const p表示这是一个指针值为常量的指针,即指针值(地址)不能修改,但是所指变量的值可以修改。 - 第三种情况,结合了上面两种情况,表示这是一个“指向常量且指针值为常量的指针”。
- 总结:从右往左读,如果
const更靠近指针p,那么就说明指针值为常量;如果更靠近int(或者其它类型名),那么说明指针所指变量为常量。
const 修饰类的成员函数
面试官 (继续提问): 好的,我们再来看 const 的第三种主要用法,也就是修饰类的成员函数。
| |
getValue()函数末尾的这个const关键字,它向编译器做出了一个怎样的承诺?- 这个承诺具体体现在
getValue()函数内部,它不能做什么事情? - 这个承诺对调用
getValue()函数的对象有什么要求?比如,一个const的MyClass对象,它能调用getValue()吗?它能调用setValue()吗?
| |
回答:
getValue()末尾的const,是在向编译器承诺:“这个getValue()成员函数,只能读取成员变量的值,而不能做任何修改。”- 具体来说,这个承诺要求
getValue()内部不能修改成员变量的值,也不能调用末尾没有const的其他成员函数。 - 一个
const的MyClass对象,它只能调用同样是const类型的成员函数,而不能调用末尾没有const的成员函数。所以,它可以调用getValue(),但是不能调用setValue()。
面试官 (总结与深化): 你说的完全正确。
const 成员函数的核心:
承诺 (Contract):
正如你所说,
const成员函数承诺不会修改对象的任何数据成员。内部约束 (Internal Constraint):
- 不能修改成员变量:在
const成员函数内部,所有的非static成员变量都会被当作const对待。this->value_ = 10;这样的代码会编译失败。(但是,static类型的成员变量可以被const成员函数修改!) - 不能调用非
const成员函数:正如你补充的,它也不能调用同一个对象的任何非const成员函数。因为非const成员函数没有做出“不修改”的承诺,编译器为了维持const的安全性,禁止了这种调用。
- 不能修改成员变量:在
外部约束 (External Constraint):
const对象只能调用const成员函数。1 2 3const MyClass obj; obj.getValue(); // OK! obj.setValue(10); // Error! 编译器会阻止你,因为它害怕 setValue 会修改这个 const 对象。- 非
const对象则两者都可以调用。
this 指针的奥秘 (底层原理)
这个约束的底层原理,和 this 指针的类型有关:
- 在非
const成员函数中,this指针的类型是MyClass* const(一个常量指针,指向一个非const的对象)。 - 在
const成员函数中,this指针的类型是const MyClass* const(一个常量指针,指向一个const的对象)。
因为 const 成员函数的 this 指向的是一个 const 对象,所以它自然就不能修改对象的成员,也不能调用那些需要非 const 对象的函数了。
你对 const 成员函数的理解已经非常透彻了。
总结
面试结束
今天我们系统性地、深入地复习了 const 关键字的三大核心用法:
- 修饰变量 (vs
#define)。 - 修饰指针 (常量指针 vs 指向常量的指针)。
- 修饰成员函数 (约束内部行为和外部调用)。
你对每一个知识点的回答都非常准确和深入,展现了你扎实的 C++ 基础。这次复习非常成功!