1、const的作用
1.1、定义常量
const int a; //a是一个常整型数
int const a; //与上一句意义一样
const int *a; //a是一个指向常整型数的指针(整型数不可修改,指针a可以修改)
int * const a; //a是一个指向整型数的常指针(整型数可以修改,指针a不可修改)
int const * const a; //a是一个指向常整型数的常指针(整型数不可修改,指针a也不可修改)
类的const成员常量需要在构造函数的成员初始化列表里进行初始化赋值。
1.2、修饰函数参数、返回值
函数的某个形参如果被const修饰,则表示在该函数内部不能修改这个形参的值。const修饰函数返回值用的并不是很多。
1.3、修饰函数体
在类中,某个函数体被const修饰,则在该函数中不能修改任何成员变量的值。
class CTestConst
{
public:
CTestConst()
{
m_iValue = 2;
m_bGetValue = false;
}
int GetValue() const; //const方法
int GetValue(); //非const方法
private:
int m_iValue;
bool m_bGetValue;
};
int CTestConst::GetValue() const
{
return m_iValue;
}
int CTestConst::GetValue()
{
m_bGetValue = true;
return m_iValue;
}
在CTestConst类中有两个同名函数GetValue,一个被const修饰,一个没有被const修饰,这个是合法的。C++中
允许通过const实现函数重载功能。在被const修饰的GetValue函数中不能修改CTestConst类的任何非静态成员变量(
const方法中可以修改静态成员变量,原因请看
const方法中能修改静态成员变量的原因)。但非const类型的GetValue函数则可以修改成员变量。同时
const方法不能调用非const方法,但
非const方法可以调用const方法。
2、同时存在const和非const函数时
如果在CTestConst类中,同时存在const类型的GetValue函数和非const类型的GetValue函数。那么怎么决定要调用哪个GetValue函数呢?规则是const对象调用const方法,非const对象调用非const方法。
CTestConst test1; //非const对象
const CTestConst test2; //const对象
test1.GetValue(); //调用非const方法
test2.GetValue(); //调用const方法
3、只存在const函数时
如果在CTestConst类中,只存在const类型的GetValue函数时。那么const对象和非const对象都可以调用const类型的GetValue函数。
CTestConst test1;
const CTestConst test2;
test1.GetValue(); //调用const方法
test2.GetValue(); //调用const方法
4、只存在非const函数时
如果在CTestConst类中,只存在非const类型的GetValue函数时。则const对象不能直接调用非const类型的GetValue函数
CTestConst test1;
const CTestConst test2;
test1.GetValue(); //调用非const方法
test2.GetValue(); //编译错误
可以使用
const_cast类型转换符在这种情况下让test2对象调用非constt类型的GetValue函数。
CTestConst test1;
const CTestConst test2;
CTestConst &test3 = const_cast<CTestConst &>(test2);
test1.GetValue(); //调用非const方法
test3.GetValue(); //调用非const方法
思考:
我们定义了test2对象为const类型的目的当然是为了保证test2对象的成员变量不被改变。在上面的例子中test3是test2引用,通过test3可以调用非const类型的GetValue函数,但在非const类型的GetValue函数中我们改变了m_bGetValue的值。上面代码能够运行成功,并且test2对象的m_bGetValue的值也确实被设置为了true。但这样就违背了我们定义test2为const类型的初衷(保证test2对象的成员变量不被改变)。所以在实际开发中我们要先能保证在非const类型的GetValue函数中没有修改任何成员变量(即去掉非const类型的GetValue函数中m_bGetValue = true这条语句),然后才能用const_cast进行转换。
5、const_cast用法
定义:const_cast <new_type> (expression) 且只能用于指针和引用
const_cast用于去除对象的const属性,但对于const数据我们要这样保证:绝对不对const数据进行重新赋值,所以使用const_cast去除const限定的目的绝对不是为了修改它的内容,只是出于无奈。比如:
1、我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数确实const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。
2、const对象想调用自身的非const方法,但我们知道在这个非const方法中不会更改任何非静态成员变量。这时候也可以使用const_cast。