const 在C++中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。
1.const的作用
1.可以定义Const常量:
const int a = 1;
2.便于进行类型检查:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行字符检查,而对只能进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
void test(const int a){}
//对传入的参数进行类型检查,不匹配进行提示
3.可以保护被修饰的东西,防止被修改,增强程序健壮性。const修饰的变量,如果被修改则会报错。
4.可以很方便的进行参数的调整和修改。因为const会保护被修饰的参数,所以只要对这个参数进行调整修改,那么这个参数在每个地方都会做出相应的改变。
5.为函数重载提供了一个参考
class A
{
void test(int a){}
void test(int a) const{}//上一个函数的重载。
};
6.可以节省空间,避免不必要的内存分配。const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出了立即数,所以const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有多个拷贝。
#define p1 3.141 //常量宏
const double p2 = 3.141;//此时并未将p2放入ROM中。。。
double a = p2;//此时为p2分配内存,以后不再分配
double a = p1;//编译期间进行宏替换,分配内存
double b = p2;//没有内存分配
double c = p1;//在进行宏替换又一次分配内存
7.提高了效率:编译器不对普通常量分配空间,而是将他们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得他的效率也很高。
二。const的使用
1.const定义常量
(1)const修饰变量
TYPE const ValueName = value;
const TYPE ValueName = value;
//以上俩行代码在本质上是一样的,都表示:被const修饰的类型为TYPE的变量ValueName的值value是不可变的
(2)将const改为外部链接,作用于扩大至全局,编译时会分配内存,并且可以不进行初始化,仅仅作为声明;编译器认为在程序其他地方进行了定义。
extend const TYPE ValueName = value;
2.指针使用const。
(1)指针本身是常量不可变
(char*) const p;
const (char*) p;
(2)指针所指向的内容是常量,不可变
const (char) *p;
(char) const *p;
(3)俩者都不可改变
const char* const p;
(4)区别方法,以*作为分界
如果const位于*左侧,则const用来修饰指针所指向的变量,即指针指向为常量。
如果const位于*右侧,则const就是修饰指针本身,即指针本身就是常量。
3.函数中使用const
(1)const修饰函数参数
a.传递过来的参数在函数内不可以改变(无意义,因为a本身就是形参)
void test(const int a);
b.参数指针所指向的内容为常量不可改变
void test(const char* a)
c.参数指针本身为常量不可变(无意义,因为int* a也是形参)
void test (int* const a);
d.参数为引用,为了增强效率同时防止修改,修饰引用参数时:
void test(const class& a);//引用参数在函数内不可以改变
void test(const TYPE& a);//引用参数在函数内为常量不可以改变
(2)const 修饰函数返回值
const修饰函数返回值其实用的并不是很多,它的含义和const修饰普通变量以及指针的含义基本相同。
a. const int fun1() //这个其实无意义,因为参数返回本身就是赋值。
b. const int * fun2() //调用时 const int *pValue = fun2();
//我们可以把fun2()看作成一个变量,即指针内容不可变。
c. int* const fun3() //调用时 int * const pValue = fun2();
四、const修饰类成员函数.
在成员函数后加const,const修饰this指针所指向的对象,也就是保证调用这个const成员函数的对象在函数内不会被改变
const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值,如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为const成员函数。注意:const关键字不能与static关键字同时使用,因为static关键字修饰静态成员函数,静态成员函数不含有this指针,即不能实例化,const成员函数必须具体到某一实例。
class Date
{
public:
void Display()const
{
cout<<_year<<_month<<endl;
}
private:
int _year;
int _month;
};
void Teat()
{
Date d1;
d1.Dispaly();
Date d2;
d2.Display();
}
思考:
1.const对象可以调用非const成员函数ANDconst成员函数么?
答:const对象只可以调用const成员函数。
因为常对象那么就意味着该对象的数据成员是不能修改的(除非使用mutable修饰的可变成员外),而那些非const成员函数存在修改数据成员的风险。So,C++要求只能调用const成员函数。
2.非const对象可以调用非const成员函数ANDconst成员函数么?答:可以。
class A
{
public:
void Display() const;
}
如上所示,通过将类成员函数声明为const,以表示这个函数不可以修改类对象。任何不可以修改数据成员的函数都应该声明为const,如果在编写const成员函数时,不慎修改了数据成员, 或者调用了其他的非const函数,则此时编译器会指出错误,这样做的函数是提高了程序的健壮性。
在相同的函数参数及相同的名字的情况下,const函数与非const函数可以构成重载函数,但是const成员函数不能改变任何的非静态变量
const函数与非const函数的调用规则
- const对象默认调用const成员函数,非const对象默认调用非const成员函数;
- 若非const对象想调用const成员函数,则需要显示的转化,例如(const Student&)obj.getAge();
- 若const对象想调用非const成员函数,同理进行强制类型转换const_cast < Student&>(constObj).getAge();(注意constObj一定要加括号)
当类中只有一种函数存在的情况
- 非const对象可以调用const成员函数或者非const成员函数
- const对象只能调用const成员函数,若直接调用非const成员函数编译器会报错。
3.const成员函数可以调用其它的const成员函数 非const员函数么?
答:const成员函数可以调用其他的const成员函数,但不能调用非const成员函数。
4.非const成员函数内可以调用其它的const成员函数 非const成员函数么?
答:都可以