记录在B站学习黑马程序员课程的时候产生的疑问和自己的理解
案例代码来自黑马程序员视频课程中的例程:
PersonAddAge00想要实现将p1的年龄加到p2上
PersonAddAge01想要实现将p1的年龄多次加到p2上
PersonAddAge02想要测试返回引用Person&时,如果改为返回Person值会产生的影响
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
this->age = age;
}
//实现将一个人的年龄加到另一个人的年龄上
void PersonAddAge00(Person &p)
{
this->age += p.age;
}
//实现连续将一个人的年龄加到另一个人的年龄上
Person& PersonAddAge01(Person &p)
{
this->age += p.age;
return *this;
}
//测试案例
Person PersonAddAge02(Person &p)
{
this->age += p.age;
return *this;
}
int age;
};
//将一个人的年龄加到另一个人的年龄上
void test00()
{
Person p1(10);
Person p2(10);
p2.PersonAddAge00(p1);
cout << "p2的年龄为:" << p2.age << endl;
}
//将一个人的年龄多次加到另一个人的年龄上
void test01()
{
Person p1(10);
Person p2(10);
p2.PersonAddAge01(p1).PersonAddAge01(p1).PersonAddAge01(p1);
cout << "p2的年龄为:" << p2.age << endl;
}
//测试案例
void test02()
{
Person p1(10);
Person p2(10);
p2.PersonAddAge02(p1).PersonAddAge02(p1).PersonAddAge02(p1);
cout << "p2的年龄为:" << p2.age << endl;
}
int main()
{
test00();//20
test01();//40
test02();//20
system("pause");
return 0;
}
如果想要将p1的年龄连续加在p2上,常出现以下错误代码:
p2.PersonAddAge00(p1).PersonAddAge00(p1).PersonAddAge00(p1);
错误的原因在于首次调用PersonAddAge00后的结果是p2.PersonAddAge00(p1) ,这不是一个Person类型的对象,所以后续的调用不成立。
void PersonAddAge00(Person &p)
{
this->age += p.age;
}
如果想要连续调用,需要让函数返回一个Person类型的对象,这样才可以连续调用加年龄的函数,形如PersonAddAge01:
Person& PersonAddAge01(Person &p)
{
this->age += p.age;
return *this;
}
其中返回值return *this中的this指向p2的地址,所以*this就是p2地址中的内容,也就是p2
那么首次调用PersonAddAge01后的结果p2.PersonAddAge01(p1)就是一个Person类型的对象,后续的调用当然成立。
函数的返回值写成Person&,是针对返回值的引用,目的在于使每次调用的返回值始终是原始的p2,而不是新建的p2'
针对这个问题,专门引入测试函数PersonAddAge02,目的是测试如果返回值不加引用的话会有什么样的结果:
Person PersonAddAge02(Person &p)
{
this->age += p.age;
return *this;
}
如果连续调用PersonAddAge02函数:
p2.PersonAddAge02(p1).PersonAddAge02(p1).PersonAddAge02(p1);
结果为20,说明只有第一次加年龄成功,在这里我的理解是return *this和Person的组合导致了第一次的调用"p2.PersonAddAge(p1)" 让p2被加上p1的年龄,但是返回的却是一个新建的Person类型的对象p2',进而导致p2'成为参加第二次调用的对象,即第一次调用后的代码可以表示为:
p2'.PersonAddAge02(p1).PersonAddAge02(p1);
以此类推,第二次调用后:
p2''.PersonAddAge02(p1);
第三次调用后:
p2''';
即最终的正确结果 = 40 存在于这个没有名字的对象p2'''里面,而我们的输出语句是:
cout << "p2的年龄为:" << p2.age << endl;
这就导致了输出的结果是上面被加了一次p1年龄但是没有被返回的p2 = 20(可怜的p2)