1.const关键字
c语言关键字const是constant的缩写,意思是不变的。当程序员定义了一个const对象,则编译器就不允许程序员再对该对象进行修改,相当于该对象仅仅是一个只读对象。const语法变化多端,而且许多面试中也会涉及到const的相关知识点。所以在此做一个总结,加深一下const的印象,也方便自己以后回顾相关的知识点。
2.定义一个const对象
定义一个const对象非常简单,只要对普通的对象加上const的修饰成了一个const对象:
const int i = 10;
const double j = 6.6;
一旦被const修饰后,任何对该对象的修改都是不被编译器允许的
const int i = 10;
i = 20; // error 编译失败,i是只读的,不能修改i的值
注意:由于const对象是不能被修改的,所以在定义const对象时必须初始化。
const int i ; //error 未进行初始化,编译失败
3.const引用
在c++中引用的类型需要和所引用的对象类型严格一致,但是给引用加上const修饰符,使其成为一个const引用之后则可以突破这一限定,c++允许const引用绑定非常量对象,字面值甚至是表达式。
普通的引用:
int i = 10;
int &a = i; // 正确
double &b = i; //error i的类型和b的类型不一致
const int i = 10;
int &a = i;//error 普通引用不能引用常量
int &b = 10;// error 同理,不能绑定常量
为何普通引用不能绑定常量?因为避免通过引用修改常量的值,因此将普通引用绑定const对象是不合法的。
const引用:
const int i = 10;
const int &a = i;//ok const引用绑定const对象
const int &b = 10;// ok const引用绑定常量
double i = 9.9;
const int &a = i;// ok 相当于做了强制类型转换
小结:非const引用只能绑定与该引用类型相同的对象;const引用则可以绑定与引用类型不同但是相关联的对象上。
4.const指针
const指针是const知识中的一个重点,也是非常容易记混淆的地方。const修饰指针的用法主要有以下几种:
第一种:const修饰*(指针)
int i = 10;
int *const p = &i;
上述的定义语句则是定义了一个指向整型对象的常指针,即const修饰的是指针,指针的指向不可以改变,但是指针所指之物是可以被改变的,如下:
int i = 10;
int j = 20;
int *const p = &i;
*p = 20; // ok 指针所指之物的值是可以改变的
p = &j; // error 指针的指向只能是i,而不能被变更到j
第二种:const修饰被指物
const int i = 10;
const int *p = &i;
/********下面这种定义也可以*********/
int i = 10;
const int *p = &i;// i可以不是常量
上述的定义语句则是定义了一个指向常量的指针。const修饰的是int,即指针的指向可以改变,但是指针所指的内容不能被改变,也就是不能通过指针修改其值。
int i = 10;
int j = 20;
const int *p = &i;
*i = 20; //error 不能修改指针所指的内容
p = &j; // ok 可以修改指针的指向
第三种:const修饰被指之物和指针
int i = 10;
const int *const p = &i;
上述的定义语句则是定义了一个指向常整型对象的常指针。int和*都被const修饰,所以指针的指针指向不能被改变,被指之物也不能被改变。
int i = 10;
int j = 20;
const int *const p = &i;
*p = 20; //error 被指之物是const,不能被改变
p = &j; // error 常指针不能改变指向
小结:const与指针的结合主要有以上几种用法,究竟是修饰指针还是修饰类型,只需要记住:如果关键字const出现在星号左边,则被指物是常量;如果出现在星号右边,则表示指针自身是常量;如果出现在星号两边,则被指物和指针都是常量,都不允许被改变。
另外需要值得注意的是:
const对象的地址只能用const指针来保存
const int i = 10;
int *p = &i; // error 只能用const指针来保存
const int *p = &i; //ok
5.const和类成员
const也可以修饰类的成员函数。一般情况下,如果在一个类中的函数不会修改类的其他数据成员时,则最好用const加以修饰。常成员函数的说明格式如下:
<类型> <函数名> (<参数>) const
一旦成员函数被声明为常成员函数,如果该函数修改了数据成员或者调用了其他非const函数,则会引起编译器报错。另外如果const修饰的是一个类,则该类的所有数据成员都无法被修改。
const修饰函数也是函数重载的一个方法,并且const对象默认调用const成员函数,如下:
#include <iostream>
using namespace std;
class A{
public:
A(int a,int b)
{
ma = a;
mb = b;
}
void fun();
void fun() const;
private:
int ma;
int mb;
};
void A::fun()
{
cout << ma << endl;
}
void A::fun() const
{
cout << mb << endl;
}
int main()
{
A a(1,2);
const A b(3,4);
a.fun();
b.fun();
return 0;
}
结果如下:
1
4
这就说明普通对象a调用了普通成员函数,const对象b则调用了const成员函数。
const除了修饰类的成员函数,也可以修饰类的成员变量。但是被const修饰的成员变量只能在构造函数的初始化列表中进行初始化,而不能在类中进行初始化。
#include <iostream>
using namespace std;
class A{
public:
A():i(100) // ok 使用初始化列表初始化
{
}
void fun()
{
cout << i << endl;
}
private:
const int i = 100; // error 不能在类中初始化
};
int main()
{
A a;
a.fun();
return 0;
}
但是在类中初始化也不会报错,只是好像对它初始化没有意义,如下:
#include <iostream>
using namespace std;
class A{
public:
A():i()
{
}
void fun()
{
cout << i << endl;
}
private:
const int i = 100;
};
int main()
{
A a;
a.fun();
return 0;
}
输出结果:
0
可以看出在类中进行的初始化并没有起到效果。
好了,夜色降临,睡觉!