C++中没有使用 引用 造成的问题

先上代码:

#include <iostream>
using namespace std;
#include <string>

class Person
{
public:
	int weight;
	Person(int weight)
	{
		//this指针指向 被调用的成员函数 所属的对象,即谁调用该函数,this指针指向谁
		this->weight = weight;
	}

	Person Add(Person &p)
	{
		this->weight = this->weight + p.weight;
		return *this;
	}
};
int main()
{
	Person p1(10);
	Person p2(10);
	p2.Add(p1).Add(p1).Add(p1);
	cout << "p2的体重是:" << p2.weight << endl;
	system("pause");
	return 0;
}

写这段代码的目的是为了学习this指针。this指针可已返回对象本身。所以 p2.Add(p1).Add(p1).Add(p1); 语句可以实现p2体重加上多个p1体重的效果。

但是问题来了。

运行结果如下:
在这里插入图片描述
这结果不对啊,怎么就加了一个p1?这怎么会回事??为了查找问题,我试着在类方法Add上增加了一句来显示运行过程的语句。

Person Add(Person &p)
	{
		this->weight = this->weight + p.weight;
		cout << "的weight是:" << this->weight << endl;
		return *this;
	}

之后运行结果如下:
在这里插入图片描述
???不对啊,都已经加到40了,怎么最后又变成20了??

嗯,好像发现哪里不对劲了。是不是产生了匿名对象??

于是为了验证猜想,将代码小改了一下,如下:

class Person
{
public:
	int weight;
	string name = "p3";
	Person(int weight, string name)
	{
		//this指针指向 被调用的成员函数 所属的对象,即谁调用该函数,this指针指向谁
		this->weight = weight;
		this->name = name;
	}
	Person(const Person& p)
	{
		weight = p.weight;
	}
	Person Add(Person &p)
	{
		this->weight = this->weight + p.weight;
		cout << this->name <<"的weight是:" << this->weight << endl;
		return *this;
	}
};

int main()
{
	Person p1(10, "p1");
	Person p2(10, "p2");
	p2.Add(p1).Add(p1).Add(p1);
	cout << "p2的体重是:" << p2.weight << endl;
	system("pause");
	return 0;
}

我在类中增加了一个属性name,给了他一个默认值p3,同时,重写了拷贝构造函数,拷贝函数中只拷贝属性weight。这样,当Add方法中的this->name打印出p3的时候就知道这是产生匿名对象了。

果然,出现了匿名对象:
在这里插入图片描述
这不对啊,怎么会出现匿名对象。。。。

哦,马虎了。类方法Add的返回值没加 & ,所以其返回值是一个Person对象。

首先,看第一部分p2.Add(p1),对象p2调用了Add方法,输入参数为p1对象,由于是p2直接调用,所以该步确实修改了p2的weight属性,变为20.

然后,在执行==p2.Add(p1)==后会又一个返回值,返回值为*this。在该步中,是p2调用的Add方法,所以this指针是指向p2的指针,*this就是p2对象本身。当一个方法进行值返回返回对象时,返回的并不是对象的本身,而是给对象的拷贝。想要验证的话很简单,在拷贝构造函数中添加一个输出:

Person(const Person& p)
	{
		weight = p.weight;
		cout << "拷贝构造函数的调用" << endl;
	}

运行结果如下:
在这里插入图片描述
可以看到,在输出p2的weight是:20后,调用了拷贝构造函数。所以其返回了一个匿名对象,这个匿名对象是p2的拷贝。

再然后,==p2.Add(p1).Add(p1)在此调用了Add方法,是p2.Add(p1)的返回值调用了Add方法,而p2.Add(p1)==的返回值是一个匿名类,所以其调用Add方法修改的是该匿名类中的属性,并不是p2的属性,所以p2的weight依旧是20。

==p2.Add(p1).Add(p1).Add(p1);p2.Add(p1).Add(p1)==同理。

所以最后,p2的weight的值是20。

正确的写法应该是:

Person& Add(Person &p)
	{
		this->age = this->age + p.age;
		cout << this->name <<"的age是:" << this->age << endl;
		return *this;
	}

运行结果如下:
在这里插入图片描述
Add方法的返回值应该是一个Person对象那个的引用。

这样 p2.Add(p1) 返回的就是p2的一个引用,相当于p2本身。所以p2.Add(p1).Add(p1) 中再次调用Add方法的就是p2,而不是匿名类。在运行结果中同样可以看出,因为整个运行过程中都没有调用拷贝构造方法。

引用虽然是个好东西,但是也要细心啊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值