C++中的const

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; }

从上边代码中可以得到两个结论:

  1. 类中的常量成员函数不可修改数据成员
  2. 类的常量对象不可调用非常量成员函数

 

上边我们只得到了结论,但是深层次的原因是什么呢?我们还要从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;
};

 

posted @ 2020-02-10 17:56  强威  阅读(157)  评论(0编辑  收藏  举报