在C++中,类中的成员函数和成员变量是分开存储的,特点如下:
1.非静态成员变量属于类的对象上;
2.静态成员变量由所有对象共享;
3.非静态成员函数和静态成员函数都由所有对象所共享。
综上所述,只有非静态成员变量才属于类的对象上。
那么问题来了,类的非静态成员函数是如何区分是哪个对象在调用自己呢?这就需要用到this指针。this指针有如下特点:
1.指向当前调用成员函数的对象;
2.是一个指针常量,即确定指向后不能随意修改指向。
3.this指针是隐含每一个非静态成员函数内的一种指针;
4.this指针不需要定义,直接使用即可。
关于this指针的用途,我们用如下代码来一一展示
Person类设计(包含在Person.h头文件中)
#pragma once
#include<iostream>
class Person {
private:
int age; // 年龄
int height; // 身高
public:
// 设定年龄
void setAge(int age);
// 设定身高
void setHeight(int height);
// 获取年龄
int getAge();
// 获取身高
int getHeight();
// 有参构造函数
Person(int age, int height);
};
用途1:当形参和成员变量同名时,解决变量名冲突
#include"Person.h"
// 设定年龄
void Person::setAge(int age) {
this->age = age;
}
// 设定身高
void Person::setHeight(int height) {
this->height = height;
}
类中有两个私有成员变量:age和height;类中两个成员函数setAge和setHeight是用于给两个私有成员变量赋值的函数,但它们的形参分别也叫age和height,这就出现了变量名冲突,此时就需要用this指针来区分成员变量名和形参名。
用途2:在类的非静态成员函数中返回对象本身,可使用return *this
我们在Person.h头文件中添加如下函数的声明
// 添加年龄
Person& addAge(Person p);
其实现如下
// 添加年龄
Person& Person::addAge(Person& p) {
int hisAge = p.getAge();
this->age += hisAge;
return *this;
}
主函数代码如下
#include"Person.h"
int main() {
// 用有参构造函数实例化对象p1
Person p1(10, 170);
// 用有参构造函数实例化对象p2
Person p2(10, 170);
cout << "调用函数前:p2.age = " << p2.getAge() << endl;
// 调用addAge函数,把p1的年龄增加到p2的年龄上
p2.addAge(p1).addAge(p1);
cout << "调用函数后:p2.age = " << p2.getAge() << endl;
return 0;
}
运行结果如下
为了直观看出this指针在这里的作用,我们做一个对比实验——把addAge函数返回值类型改成void
发现编译器在下图14行报错
报错的原因很简单,因为返回值类型是void,因此p2.addAge(p1)并非一个对象,所以不能用这种链式方法再次调用成员函数addAge,这也就无法通过这种链式方法实现年龄的累加。 而如果要实现这种链式方法实现年龄累加,我们就必须保证addAge函数的返回值依然是该对象本身,因此需要return *this。
小彩蛋:addAge函数的返回值类型改为Person,运行结果如下图所示
原因是值返回的方式返回的对象已经不是p2本身,而是调用拷贝构造函数创建了一个新的对象p2',所以若要返回对象本身,必须返回对象的引用。