C++ const成员方法写法由来

前言

对于学过其他编程语言的人来说,C++的const成员方法的写法无疑是相对来说比较罕见的一种写法了。当然,也由于这种罕见古怪的写法,很多不懂为何这么写的人盆友们,甚至在使用的时候,都会忘记如何去写一个const成员方法。

弄懂const

先看词典上对于const的解释,如下图:
image.png
常量。我们对于常量的理解,就是不能被再次修改
在C++中,const可以用于修饰变量、非静态成员方法和成员变量(包括静态成员变量和非静态成员变量)
我们这里要搞懂const修饰非静态成员变量的话,就得先搞懂const修饰普通的变量了。

const修饰变量

const修饰变量,只需谨记一点即可,那就是:const放在哪个的前面,那么const修饰的就是后面那一坨东西,那一坨东西就不能被修改,同时,变量类型可以忽略不看
举个例子:

int const num = 10;

这段代码就表示了:num这个变量的值是不允许被修改的,如果出现下列的操作,那么就会报错

int const num = 10;
num = 20;//这局代码就会报错

变量类型可以忽略不看

int const num = 10;
const int num = 10; //这两句代码是一样的

变量类型可以忽略不看 ,这里的意思就是:const写在int的前和后是没关系的,结果都是一样的
通过上面的这个例子,盆友们可能还看不出个所以然来,因为const修饰普通的非指针类型变量的时候,都是不会有任何歧义的。给人容易造成难以理解的是const修饰指针变量的时候。请看以下代码:

int a = 10;
int const *p1 = &a;
int * const p2 = &a;

当修饰的是指针变量的时候,这句话就至关重要了:const放在哪个的前面,那么const修饰的就是后面那一坨东西,那一坨东西就不能被修改
现在就来解释分析

int a = 10;
int const *p1 = &a;

现在我们套用这句话,当为上面这种代码,const放在 * 的前面,那么const修饰的就是后面那一坨: *p1,意思就是 *p1 将不能被修改,也就是说,当出现下面这样代码的时候,就会报错

int a = 10;
int const *p1 = &a;
*p1 = 20; //这句代码就会报错,因为const修饰的是 *p1。这就说明了,将不能修改指向地址里存储的值。但是可以修改指向的地址

int b = 20;
p1 = &b; // 这句代码就是对的

同理,当是下面这种代码

int a = 10;
int * const p1 = &a;

现在我们套用这句话,当为上面这种代码,const放在了 p1 前面,那么const修饰的就是后面那一坨: p1,意思就是 p1 将不能被修改,也就是说,当出现下面这样代码的时候,就会报错

int a = 10;
int b = 20;
int * const p1 = &a;
p1 = &b; //这句话就会报错,因为const修饰的是p1。这也说明了,p1将不能修改指向的地址。但是可以修改指向地址存储的内容值

*p1 = 20; // 这句代码就是对的
总结

重要的事,多说几遍没错
const放在哪个的前面,那么const修饰的就是后面那一坨东西,那一坨东西就不能被修改

弄懂this指针

弄懂了const之后,现在我们离我们的目标越来越近了。但是要完全弄明白 const成员方法写法的由来 还得搞懂this指针是怎么来的
现在先看下面的代码

class Person {
  int age = 0;
public:
  int getAge() {
    return age;
  }
  void setAge(int newAge) {
    age = newAge;
  }
int main() {
  Person person;
  person.setAge(20);

  return 0
}

这段代码里,请问这里的**setAge()getAge()**方法里的age是怎么被访问到的?
这里就不卖关子了,相信大家都是知道的,上面这段代码就是和下面这段代码是一样的

class Person {
  int age = 0;
public:
  int getAge() {
    return this->age;
  }
  void setAge(int newAge) {
    this->age = newAge;
  }
int main() {
  Person person;
  person.setAge(20);

  return 0
}

说白了,就是这里有一个隐形的this指针变量存在着,这个this指针变量是所有的非静态成员方法系统默认生成的。所以实际上的代码就是下面这段代码

class Person {
  int age = 0;
public:
  int getAge(Person *const this) {
    return this->age;
  }
  void setAge(Person *const this, int newAge) {
    this->age = newAge;
  }
int main() {
  Person person;
  person.setAge(&person, 20);

  return 0
}

刚刚代码的关键点就在于下面这一句代码

  Person *const this

从上面这段代码可以看出来,this实际上就是一个外部传过来的一个当前类型的对象指针,因此this是一个局部指针变量,并且还是const修饰过this的指针变量,那么从这里也能知道: 在非静态成员方法中,我们将无法改变this的指向地址,这个也是理所当然,如果this不是const的话, 那么方法内部就能随意修改this的指向,这样的话,那还得了。从这里也可以看出C++设计者的严谨之处
当然,从这里也能看出: 一个实例对象在调用非静态成员方法的时候,当前的对象是怎么传入到方法当中的,就是下面这句代码:

  Person person;
  person.setAge(&person, 20);

刚刚代码分析的关键点就在于下面这一句代码,请谨记

  Person *const this

最终章:const成员方法写法由来

现在就给出最终解释
1、因为this是系统默认生成的形参,导致自己无法自定义去修改这个this,语法上也不允许
2、由于上面这个原因,因此就只能另辟蹊径,写在函数的小括号外部
3、写在外部的话,就分为两个地方,函数名的前面和后面
4、如果写在前面的话,就容易给使用者造成是对返回值的修饰
5、因此,就选择了写在后面,后面的话,最好就是写在小括号后面了。这就是const成员函数的写法的由来

代码如下:

class Person {
 ...
 ...
 void test() const {} //const成员函数
 ...
 ...
}

这段代码等同于下面这段代码:

class Person {
 ...
 ...
 void test(Person const * const this) {} //const成员函数
 ...
 ...
}

在 * 前面增加一个const,就是为了让方法内部不能对this的非静态成员变量进行修改
希望这篇文章对技术不满足于 知其然,而喜爱追求技术 知其所以然 的盆友们有所帮助

额外知识

从整篇文章的解释,其实也能看出一个东西的原因:就是为何const修饰成员函数的时候,只能修饰非静态成员函数。原因其实很简单: 当const修饰成员函数的时候,仅仅是对this指针进行修饰,但是静态成员方法里并没有this指针,因此const就不能用于修饰静态成员方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值