【带你一次性读懂C++之this指针】
系列文章目录
? ? ? ? 欢迎大家订阅我的《计算机底层原理》、《自定向下看Java》、《深度解析C++》系列专栏,我会为大家持续输出优质文章,能够帮助到大家就是对我最大的鼓励。
目录
前言
????????
一、为什么需要this指针
? ? ? ?this指针是C++当中用于指向当前对象的指针,它是成员函数内的一个隐式参数,指向调用该成员函数的对象的内存地址(this指针存放的内容就是对象的内存地址),this指针的主要用途是在成员函数内部访问对象的成员变量和调用其他的成员函数。
????????在类的成员函数当中,如果存在与类的成员变量同名的局部变量或者函数参数,编译器可能无法区分它们,这个时候我们就需要使用this指针可以明确地指出成员变量属于当前对象。
? ? ? ? 例如像遇到这样的情况的时候,类的成员变量和构造函数当中的参数发生了冲突,那么这个时候就会需要this指针进行区分。其实想要避免这样的问题出现的话也有一个办法,就是不要让成员变量和函数的参数同名,具体怎么做取决于程序员的个人喜好。
class MyClass { public: int x; void setX(int x) { // 使用 this 指针访问成员变量 this->x = x; //x = x;如果直接这么写的话编译器会发生混淆 } };
二、this指针的使用
? ? ? ? 1.访问成员变量
? ? ? ? 我们使用this指针就可以在成员函数体内访问对象的成员变量。
class MyClass{ public: int x; public: void Print(){ cout << this -> x << endl;} }
? ? ? ? 2.调用其它成员函数
? ? ? ? 使用this指针可以在成员函数当中调用其它成员函数。这里其实是不是用this指针调用都可以在同一个类当中我们可以直接调用其它同类的成员函数,编译器可以自动识别,只不过这里使用this指针会更加地清晰明确。
class Animal { public : int age; string name; public: Animal(int age, string name) { this->age = age; this->name = name; } void Func() { this->Print(); } void Print() { cout << "Hello World!" << endl; } };
三、this指针的隐式传递
? ? ? ? 当我们在调用对象的成员函数的时候,编译器会在幕后自动地将对象的地址传递给this指针,这个过程是隐式的,程序员不需要显示地传递this指针,this指针是我们类当中的每一个非静态的成员函数的第一个隐式的参数。this指针的类型就是类的类型的指针,而且是const(注意这里的const修饰的是指针,也就意味着我们不能修改this指针的值,他只能指向对象本身。)
class MyClass { public: int x; void setX(MyClass* const this,int x) { // 使用 this 指针访问成员变量 this->x = x; //x = x;如果直接这么写的话编译器会发生混淆 } };
? ? ? ? 这里的参数是隐式的,这一步我们程序员不需要知道,而是由编译器来为我们负责,接下来我为大家详细地解释一下对于隐式的传参编译器都做了什么。代码如下:
MyClass obj; obj.setX(42); // 编译器将 &obj 传递给 this 指针
? ? ? ? 1.识别对象地址:
? ? ? ? 编译器知道obj是一个MyClass类型的对象,因此能够识别到obj的地址,也就是&obj。
? ? ? ? 2.隐式传递this指针:
? ? ? ? 当我们调用setX函数的时候,编译器会在幕后将&obj传递给this指针,实际上调用setX的底层机制是类似于这样的。obj.setX(&obj,42);
????????我们的成员函数之所以能够调用我们的成员变量并且对他们进行操作就是因为我们有this指针,我们不管是在成员函数内部是调用成员变量还是在一个成员函数内部调用另外一个成员函数都是依靠this指针。
? ? ? ? 不过到了这里可能会有小伙伴要问了你刚才不是说了调用成员变量和成员函数不需要this指针显式调用也可以吗,怎么现在又说我们不管是在成员函数内部是调用成员变量还是在一个成员函数内部调用另外一个成员函数都是依靠this指针呢?其实很简单,因为编译器帮我们做了优化,即使我们程序员自己不调用this指针,编译器也会替我们隐式地调用,只不过这一步对我们是透明的,我们看不到罢了。
? ? ? ? 就这样编译器通过隐式传递this指针,成员函数内部能够在执行时准确地操作调用它的对象成员变量,这也就是为什么可以在成员函数内部直接使用成员变量而不需要指定对象的原因,因为this指针指向当前对象。
四、this指针和const成员函数
? ? ? ? ?在常量成员函数当中,this指针就会被修饰称为const MyClass* const this,注意了这两个const关键字位置不一样用法可是天差地别,第一个const修饰的是类型,代表这个指针存储的值必须是常量也就是这个指针只能访问常量,第二个const修饰的是指针,就意味着这个指针本身一个是常量,也就意味着这个指针不能够被修改,他只能指向对象的内存地址,如果想把this指针赋值给别人是不可以的。例如
class MyClass { public: int x; void constFunction() const { // this 指针的类型是 const MyClass* // 不能修改成员变量 x int value = this->x; // 合法 // this->x = 42; // 不合法 } };
? ? ? ?这里的成员函数末尾加上const就意味着this指针指向的内容必须是一个常量,而x变量不是常量所以不能修饰。因为我们只能读取常量变量,但是不能对其进行修改。
? ? ? ? 这样设计的目的是为了确保常量成员函数不会意外地修改对象的状态,如果不加上这里的const的话,意味着成员函数可以利用this指针随意地修改对象的成员变量,会引发很多意外的操作,这么做也是为了使得它们能够被安全地用于处理对象,总之通过在成员函数声明中加上const关键字,this指针的类型被限制为指向常量的指针,从而确保在常量成员函数当中只能访问而不能修改对象。
? ? ? ? 拓展:????????这里我拓展一下,this指针属于对象内存布局当中的一个成员,如果一个对象在栈当中开辟空间那么就意味着这个this指针存储在栈上,如果这个对象利用new关键字在堆上开辟空间,那么这个this指针就在堆上存储,总之这个this指针是属于对象的,对象在哪里this指针就在哪里,这里要和Java进行区分,Java当中的对象一定在堆上,但是this指针却存放在虚拟机栈当中的局部变量表当中,所以大家这里要做好区分,语言之间不要相互混淆。
总结
? ? ? ? 今天我为大家详细地介绍了,this指针的相关用法以及特性,this指针是我们理解C++语言非常重要的基础,之后我们会频繁地使用这个概念,希望我的这篇文章能够解答小伙伴们心目当中关于this指针的疑惑。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!