1.修饰变量
const int i = 0; // i 为常量,不可修改 const int* p = &i; // 指向常量的指针 int const *p = &i; // 指针为常量,指向i不可修改 const int &r = i; // 常量引用,不可通过r修改i typedef int *po; const po p = &i; // 此时const修饰的是 int* ,所以此时指针是常量
顶层const:指针本身是常量
底层const:指针所指向的对象是常量
2.修饰函数(包括返回值,参数,函数体)
const int fun(){...} // 函数返回值为常量
void fun(const int a, const int b){...} //函数参数为常量
const如何修饰函数体(主要修饰类的成员函数):
class TestClass
{
public:
TestClass() : val(100) {}
~TestClass() {}
int getVal_v1()
{
return val;
}
int getVal_v2() const
{ // val ++; 编译报错,常量成员函数不可修改数据成员
return val;
}
private:
int val;
};
int main()
{
TestClass t;
int a = t.getVal_v1(); // 正确,非常量对象调用非常量成员函数
int b = t.getVal_v2(); // 正确,非常量对象调用常量成员函数
const TestClass tc;
int a = tc.getVal_v1(); // 编译报错,常量对象不可调用非常量成员函数
int b = tc.getVal_v2(); // 正确
return 0;
}
从上边代码中可以得到两个结论:
- 类中的常量成员函数不可修改数据成员
- 类的常量对象不可调用非常量成员函数
上边我们只得到了结论,但是深层次的原因是什么呢?我们还要从this指针说起。。。
当我们通过对象调用类的成员函数时,成员函数是如何找到类的数据成员的呢?比如上边代码中的t.getVal_v1(); 这句代码可以等价为 t.getVal_v1(this); 在调用过程中编译器会将this指向调用对象 this = &t; 然后在成员函数内部,通过this指针来获取数据成员。
但问题就出在this是一个常量指针,指向某个对象后,就不可以再指向别的对象。在成员函数的参数列表后加一个const就是用来修饰this的,使得this从常量指针变为常指针常量,也就是指针以及指针所指向的对象都是常量。
所以在 getVal_v2() 成员函数中,不能通过常指针常量 this 修改数据成员。
将对象定义为const常量之后,那么非常量指针this是不能指向该对象的。
但 常量成员函数不可修改类的数据成员 这句话并不绝对,因为有 可变数据成员 mutable,如下例所示:
class TestClass
{
public:
TestClass() : val(100) {}
~TestClass() {}
int getVal_v2() const
{
val ++; // 正确,因为val是可变数据成员
return val;
}
private:
mutable int val;
};
来源:https://www.cnblogs.com/qiang-wei/p/12291879.html