通常有

  • const qualifier
  • member-function const

Const Qualifier

C++ Primer pp64

分为 Top-levelLow-level Const 。

  • Top-level : the pointer itself is a const.
  • Low-level : a pointer can point to a const object
    • 注意: all pointer/reference to a const object must have a const type.
// 如果底层是 const object, 那么顶层的 pointer 和 reference 也必须是 const .
const int n = 10; 
int* pn = &n;  // 错误

// 但如果底层是 non-const object, 那么 pointer 和 reference 就无所谓了。
int n = 10; 
const int *pn = &n; 
int n = 0; 
// Top-level const: const pointer  
int *const p1 = &n; // 读法: const pointer 
// const reference is meaningless. 

const int cn = 0; 
// Low-levle const: a point to const object  
const int *p2 = &cn; 
const int *const p3 = &cn;

注意 const 只是修饰词,是有办法去除的。

由于 const object 只是内存中的一个对象,所以可以通过指针和 dynamic_cast 修改。

但没人会这么做,因为行为是未定义的 (完全取决于编译器怎么处理 const)。


Const Member Function

Declaring a member function with the const keyword specifies that the function is a “read-only” function that does not modify the object for which it is called.

不会修改 this 对象的内容 (这句话很重要)。

可以修改 指针所指对象StaticMutable

  • 应用1可以修改 mutable data member
  • 隐患1 : 可以修改 指针类型的数据成员所指向的对象
    • Microsoft Docs 早就说明了,不会修改 this 对象的内容
    • 显然只有内存地址(指针)才算是 this 对象内容
  • 可以修改 static data member
    • Microsoft Docs 早就说明了,不会修改 this 对象的内容
    • 但是 static 不算 this 对象的内容。 C++ 真的是贯彻执行啊。
  • 不能修改 const data member (废话)
  • 不能修改 除 static, mutable 以外的 Data Member
  • 不能调用 non-const member function

应用 1: Mutable 的作用

详情 https://randoruf.github.io/2021/08/15/cpp-mutable.html

隐患 1: 可以 “修改指针类型的数据成员所指向的对象”

https://blog.csdn.net/fukaibo121/article/details/71511229

指针的对象不是 this 内容

class A{
public:
    int* px; 

    A () {px = new int(10);}
    ~A() {delete px;}
  
    void setP() const{*(px) = 99;}
}; 

int main(){
    A a; 
    std::cout << *(a.px) << std::endl; 
    a.setP(); 
    std::cout << *(a.px) << std::endl; 
}

注意, 如果你以数组声明,那么还是属于 this 对象内容

所以不能通过 const 成员函数修改。

强制转换去除 const

但可以通过指针强制转换 来去除 const (const 函数是靠 const reference 实现的)。

class A{
public:
    int arr[100]; 
    A () {}
}; 

int main(){
    A a; 
    // sizeof 既可以查看 对象大小 sizeof(a),也可以查看 类大小 sizeof(A)。
    std::cout << sizeof(a) << std::endl; 
}
void populate(int* arr, int len){
    for (int i = 0; i < len; i++){
        *(arr + i) = i;
    }
}

class A{
public:
    int arr[100]; 

    A () {}
    void setArr() const{
        // 通过指针 "强制转换" 来去除 const (const 函数是靠 const reference 实现的)。 
        // 合法。虽然编译器会尽量传入 const int ... 
        // 但是耐不住有些人写 type casting....  
        populate(const_cast<int*>(arr), 100); 
    }
}; 

int main(){
    A a; 
    a.modify(); 
    std::cout << a.arr[50] << std::endl; 
}

其他: 可以 修改 static data member

https://docs.microsoft.com/en-us/cpp/cpp/static-members-cpp?view=msvc-160

The data member is declared in class scope, but definition is performed at file scope. These static members have external linkage.

class A{
public: 
    static int cnt; 
    void increseCounter() const{
        cnt++; 
    }
    A () {}
}; 

// Define cnt in file scope.
int A::cnt = 0; 

int main(){
    std::cout << A::cnt << std::endl; 
    A a; 
    for (int i = 0; i < 10; i++){
        a.increseCounter();    
    }
    std::cout << A::cnt << std::endl; 
}

关于 Static Member Function

Static Member Function 是属于全体对象的。即使没有具体 this 对象存在,也可以通过 Class:: 调用。

显然 Static Member Function 只能访问 Static Data Member (因为不需要对象存在) 。

但是 Static Data Member 可以被 Non-staticStatic Member Function 访问。

class A{
public: 
    static int cnt; 
    static void increseCounter(){
        cnt = 99; 
    }
    A () {}
}; 

// Define cnt in file scope.
int A::cnt = 0; 

int main(){
    std::cout << A::cnt << std::endl; 
    A::increseCounter();    
    std::cout << A::cnt << std::endl; 
}

参考

https://blog.csdn.net/fukaibo121/article/details/71511229

https://docs.microsoft.com/en-us/cpp/cpp/mutable-data-members-cpp?view=msvc-160

https://docs.microsoft.com/en-us/cpp/cpp/const-cpp?view=msvc-160