03-2 this指针
在 03-1 成员变量和成员函数分开存储 中,我们知道了在 c++中,类中的成员变量和成员函数是分开存储的。简单复习一下:
在c++中,只有类内的非静态成员变量才属于对象上,其他的(静态成员对象、成员函数)都不属于对象上。
没一个非静态的成员函数只会诞生一份函数实例,也就是所多个同类的对象会共用一块代码。那么,这一块代码如何区分是哪个对象调用的呢?
c++中通过特殊的对象指针:this
指针,解决上述问题。 this 指针指向被调用的成员函数所属的对象。
比如一个类test
,类上有一个函数print()
,存在三个类的对象p1
、p2
和p3
。当p1
调用print()
函数的时候,this指针就指向p1
的内存地址;当p2
调用print()
函数的时候,this指针就指向p2
的内存地址...以此类推。
this
指针是隐含在每一个非静态成员函数内的一种指针。this
指针不需要定义,直接调用即可。
this
指针的用途:
- 当形式参数和成员变量同名的时候,可以使用
this
指针来区分; - 在类的非静态成员函数中返回对象本身的时候,可以使用
return *this
。
我们围绕着用途来看看:
-
当形式参数和成员变量同名的时候,可以使用
this
指针来区分(解决名称冲突)(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)#include
using namespace std; class Person { public: int age; Person(int age) { this->age = age; } }; void main() { class Person p1(18); cout << "p1的年龄:" << p1.age << endl; } p1的年龄:18
但是如果我们不标注
this
,比如说这样:Person(int age) { age = age; }
那么传入的
age
又再一次赋值给了传入的age
。如果加上了this
比如this->age = age;
,就指明了需要被赋值的age
是类内的age
。也就是单独写的这一块代码中,出现的三个age
在编译器看来都是同一个。this
指针指向的是被调用的成员函数所属的对象。比如上面的例子中,
Person p1(18);
调用的是Person(int age)
的有参构造函数。调用这个有参构造函数的对象是p1
,所以this
指针指向的是p1
。 -
返回对象本身的时候,可以使用
return *this
。#include
using namespace std; class Person { public: int money; Person(int money) { this->money = money; } class Person& Addmoney(class Person& p) { this->money = this->money + p.money; p.money = 0; return *this; } }; void main() { class Person p1(100); class Person p2(100); class Person p3(100); class Person p4(100); cout << "p4原来持有的金钱是 " << p4.money << endl; p4.Addmoney(p1).Addmoney(p2).Addmoney(p3); cout << "p4现在持有的金钱是 " << p4.money << endl; } 运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
p4原来持有的金钱是 100 p4现在持有的金钱是 400
p4.Addmoney(p1).Addmoney(p2).Addmoney(p3);
指的是:p4
先调用函数Addmoney()
,传入值是p1
,然后使用返回的数值再次调用Addmoney()
,传入值是p2
,然后使用返回的数值再次调用Addmoney()
,传入值是p3
。而在函数
Addmoney()
,返回的是class Person
类型。而具体 return 的是*this
,在这个例子里面,this
是指向p4
的指针,而*this
就是代表p4
这个对象本体。这样的是:链式编程思想。当然,我们见过了,比如
cout
。cout
使用左移运算符(<<
)可以无限链接。比如:cout << "你好" << "我不好" << "啊?" << "我不好" << "听不见" << "n**l" << endl;
无限链接下去。如果返回的是值:
#include
using namespace std; class Person { public: int money; Person(int money) { this->money = money; } class Person Addmoney(class Person& p) //注意这边,原来是:class Person& { this->money = this->money + p.money; p.money = 0; return *this; } }; void main() { class Person p1(100); class Person p2(100); class Person p3(100); class Person p4(100); cout << "p4原来持有的金钱是 " << p4.money << endl; p4.Addmoney(p1).Addmoney(p2).Addmoney(p3); cout << "p4现在持有的金钱是 " << p4.money << endl; } 运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
p4原来持有的金钱是 100 p4现在持有的金钱是 200
如果这里返回的是值,那么就是
p4
的值再去创建,也就是使用了编译器提供的拷贝构造函数构造了一个新的对象。每一次返回都是新的对象。简单来说:如果用引用的方式返回,那么返回的是本体。如果返回的是值,那么每一次返回都是一个新的对象。
本质:
-
this
指针本质是一个指针常量,指针常量的特点是指针的指向不可以被修改。void setPerson() { this = NULL; }
如果将
this
指针修改到NULL
或者其他的内存地址上,就会报错,报错理由如下:分配到“this”(记时错误)
总结:
this
是什么:this
是一个指针,在类里出现,隐藏在每一个类中的对象中。this
有什么用:- 解决名称冲突
- 返回对象本身
- 但是还是建议在类里面加上前缀,比如说:
m_
,(m 表示 member,成员的意思)。养成良好的命名习惯......
:-)