const的使用
记录自己学习C++的点点滴滴,为了自己更好的复盘和回顾,如果可以帮助到你,我将不胜荣幸!!!
Const的使用
const关键字的用法
1. const修饰普通变量
const int a = 100;
int const a =100; //与上面等价
const修饰普通变量变为常量,常量定义时必须初始化,不能被赋值,不能被修改;与c语言中的宏定义定义常量效果很像;但是存在着差异:const的发生时机在编译阶段,会进行类型安全检查,有BUG编译时就会报错;c语言宏定义定义常量发生时机在预处理阶段,进行字符串替换,运行时才会发现出错;
2. const修饰指针
2.1、常量指针
const int * p = number;
int const *p = number;//效果同上
const在 * 前则称为常量指针,不能改变指针所指常量的值,但是可以改变指针本身的指向
6 int number = 10;
7 const int * p =&number;
8 int number2 = 100 ;
✗ 9 *p = 100;
10 number = 100;
11 p = &number2;
可以看到第9行出现了报错,因为这里发生了通过常量指针对所指常量值的改变
2.2、指针常量
int * const p = number;
当const在 * 后面时,此时称为指针常量,可以改变指针所指变量的值,但是不能更改指针所指的常量;
6 int number = 10;
7 int * const p =&number;
8 int number2 = 100 ;
9 *p = 100;
10 number = 100;
✗ 11 p = &number2;
同样是刚刚的代码,我们会发现当把常量指针修改为指针常量时,便会在11行发生报错,因为此时修改的是指针常量所指的常量
3. const修饰的类和对象
3.1、const数据成员
和常量一样,常量数据成员作为const修饰的类中的变量,有着和常量一样的特点,必须进行初始化,且不能进行赋值,
5 class Point
6 {
7 public:
8 int const iy = _ix;
9 private:
10 int _ix = 10;
11
12 };
13 int main()
14 {
15 Point p;
✗ 16 p.iy = 100;
17 return 0;
18 }
可见当我们对类的常量数据成员进行赋值时是会发生错误的
3.2、const成员函数
void print() const
{
//函数体
}
形如上面的形式,我们称之为const成员函数,const关键字放在函数的参数表和函数体之间,const成员函数有以下两个特点:
1、只能读取类数据成员,而不能修改之
2、只能调用const成员函数,不能调用非const成员函数
关于这两点其实和下面的const修饰的对象很像,我们在下面对这两点进行详细的解释
3.3、const对象
类对象也是可以用const修饰的,形如:
const Point pt(1,2);
形如上面的便称为const对象,默认情况下,const对象调用const成员函数,非const对象调用非const成员函数;
非const对象既可以调用const成员函数,也可以调用非const成员函数,const对象不可以调用非const成员函数,可以调用const成员函数;
这里我们结合this指针对const成员函数以及const对象的特点进行解释:
首先,这些特点我们是可以理解的,因为const常量的创建就是为了不被改变,那么问题来了,这些都是如何实现的呢?
其实主要是通过this指针进行实现的,我们知道每个非静态成员函数的第一个参数是有一个默认this指针,指向的是该类对象的地址,因此这个指针的指向是不可以改变的,如果改变了那么就相当于不再指向该类的对象了,因此this指针其实是一个常量指针,形如
Point * const this
对于const成员函数而言,其不仅不能修改this指向的对象,而且this指向对象的值也是不能改变的,那么在表达式后加上const实际上就是在this指针的 * 前又加了一个const,形如:
const Point * const this
使其不仅是常量指针而且还是指针常量,这样也就解释了为什么成员函数只能读取数据成员,不能修改之;
还有一点:为什么const对象可以调用const成员函数,但是不能调用非const成员函数?
关于这一点我们需要在const成员函数的this形式为const Point * const this 的基础上进行解释,如const对象调用const成员函数,那么此时const成员函数的第一个传参是 const Point * const this 形式,而此时this指针指向的const对象因为被const修饰,形如 *const Ponit **,因此是可以成功被调用的;
而当const对象调用非const成员函数,那么此时非const成员函数第一个传参是 Point * const this 形式,而此时this指针指向的const对象因为被const修饰,形如 *const Ponit ** ,因此转换时会丢失底层const,所以const对象不可以调用非const函数;
总结
这里的概念较为多,并且容易产生混乱,还是需要理解再记忆,这也是C与C++的不同点之一