C++学习笔记:const和mutable
1.const可以实现常函数
所谓的常函数,就是class
的成员函数承诺在函数内部不会修改class
的任何成员变量(注意是任何一个)。
实现语法是在函数名后面加上const
,举个栗子:
#include<iostream>
using namespace;
class person
{
public:
person(int Age):age(Age){
};
//get_age()函数只读取age的值,没有修改任何成员,因此可以是常函数
int get_age(void) const
{
return this->age;
}
private:
int age;
};
int main(int argc,char**argv)
{
person tom(15);
int age=tom.get_age();
cout<<age<<endl;
return 0;
}
输出:
15
2.C++为什么设计常函数
对于person
类的使用者来说,上面的get_age()
函数典型的用法并不是tom.get_age()
,而是通过一层封装得到新的函数来完成功能,函数通过引用来传参。例如通过获取年龄函数封装出一个打印年龄的函数:
void show_age(const person&pn)
{
cout<<"age = "<<pn.get_age()<<endl;
}
在上面的函数中,作为类的设计者,因为提前知道获取年龄并不会修改年龄这个成员,所以在get_age()
函数后加上const表面这是一个常函数。而在后面类的使用者封装show_age()
函数时,同样该函数不需要修改年龄,所以在引用前加上const
。
C++
要求一个函数传参为引用对象的时候,函数内部调用的所有类的成员函数必须是常函数。也就是说show_age()
参数为const person&pn
时,get_age()
必须实现成常函数,否则编译会报错。
思考:
C++
为什么设计const
常函数?还是为了class
的设计者和使用者更好的协作,避免错误的使用类库。
3.mutable可以局部打破const常函数
void show_age(const person&pn)
{
cout<<"age = "<<pn.get_age()<<endl;
}
对于上面的show_age()
函数,参数为const person&pn
,则函数内部对pn
调用的方法必须都是常函数方法。但是有时候个别成员变量,就是需要在const
的常函数中也能修改(注意只是个别,其他大部分是不需要修改的),
怎么办?
有2个解决方法:
- 1.去掉
const
,让它不再是常函数。 - 2.使用
mutable
局部打洞。
mutable
使用方法就是在需要局部打洞的变量前加上mutable
,举个栗子:
#include<iostream>
#include<string>
using namespace;
class person
{
private:
//在需要局部打洞的变量前加上mutable
mutable int age;
string name;
public:
person(int Age):age(Age){
};
//get_age()函数只读取age的值,没有修改任何成员,因此可以是常函数
int get_age(void) const
{
//name="zhangsan"; name不可以修改,但是也可以加mutable使其可以修改
age++;//这里age就可以修改了
return this->age;
}
};
int main(int argc,char**argv)
{
person tom(15);
int age=tom.get_age();
cout<<age<<endl;
return 0;
}
输出:
16
思考:
C++
为什么设计mutable
?本质是“先全部禁了再按需打开”的思路。先用const
把函数变为常函数,封上它修改所有成员的道路,然后用mutable
去打洞,需要修改哪个就打哪个的洞。