Categories:
C++ Const 关键字
通常有
- const qualifier
- member-function const
Const Qualifier
C++ Primer pp64
分为 Top-level 和 Low-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
对象的内容 (这句话很重要)。可以修改 指针所指对象、Static 、Mutable 。
- 应用1:可以修改 mutable data member
- 隐患1 : 可以修改 指针类型的数据成员所指向的对象
- Microsoft Docs 早就说明了,不会修改
this
对象的内容。 - 显然只有内存地址(指针)才算是
this
对象内容。
- Microsoft Docs 早就说明了,不会修改
- 可以修改 static data member
- Microsoft Docs 早就说明了,不会修改
this
对象的内容。 - 但是 static 不算
this
对象的内容。 C++ 真的是贯彻执行啊。
- Microsoft Docs 早就说明了,不会修改
- 不能修改 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-static 和 Static 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