C++ 重载赋值运算符

C++类创建时,会产生一个默认的赋值运算符函数:A&  operator=(const A&);

普通类实例之间赋值可能没问题,但当类成员变量中有指针引用的动态内存时,复制后只是简单地将指针值复制,而没有将其指向的动态内存也拷贝一份,这样即多个类实例内的指针指向同一动态内存,当类实例析构时,会导致这块动态内存delete多次而产生错误。这也就说明需要我们对一些特别的类重载其赋值运算符函数,即深拷贝!

这里只是介绍一下深拷贝的意思,不具体细说。下面是讨论赋值运算符函数的返回值。看下代码:

#include <iostream>
using namespace std;

class A{
public:
	int a;
	A(){};
	A(int n){ this->a = n; }
	operator int(){
		cout<<"use int conventor \n";
		return this->a;
	}
	A& operator=(const A a){
		this->a = a.a;
		return *this;
	}
};

int main(){
	A a, b, c(3);
	a = b = c;
	cout<<a.a<<endl;
	return 0;
}
在百度搜索时,看很多童鞋不理解为什么好多的运算符重载都返回引用?这是为了进行串联的操作,例如a = b = c =.... , cout<<a<<b<<c...

那么如果不写A&,默认的返回值是什么呢?答:是int类型

上面的代码,有两种operator函数,一种是“类型转换函数”,另一种是“操作符重载函数”。其中“类型转换函数“不能声明其返回值,大家可以这样理解,类型转换函数就是要将本类转换为其他类型,operator后面紧跟着目标类型,也就不需要再多余得写明返回值。而”类型转换函数“如果不写返回值,默认的是int类型。

下面,来看几种情况:

class A{
public:
	int a;
	A(){};
	A(int n){ this->a = n; }
	operator int(){
		cout<<"use int conventor \n";
		return this->a;
	}
	A& operator=(const A a){
		this->a = a.a;
		return *this;
	}
};

int main(){
	A a, b, c(3);
	a = b = c;
	cout<<a.a<<endl;
	return 0;
}

结果是:3

分析:a = b = c; 表达式从右往左执行,先b=c,调用了operrator=,返回b的引用,然后a = b,再调用一次operator=,返回a的引用

class A{
public:
	int a;
	A(){};
	A(int n){ this->a = n; }
	operator int(){ //与上面相比,去掉了其返回值A&
		cout<<"use int conventor \n";
		return this->a;
	}
	operator=(const A a){
		this->a = a.a;
		return *this;
	}
};

int main(){
	A a, b, c(3);
	a = b = c;
	cout<<a.a<<endl;
	return 0;
}

结果是:

use int conventor 

use int conventor

3

分析:前面说过,”运算符重载函数“的默认返回值是int类型,所以在return *this时,会调用operator int,将A类型转换成int类型。所以b=c时,调用operator=,然后在返回时又调用了一次operator int,返回了int值,为3。接下来就变成了 a= 3的表达式,这个怎么办呢?这个表达式,会调用A(int n)这个”转换构造函数“,将3转换成A的一个临时对象,然后调用operator=将临时对象复制到a中,同样,operator=在返回时又调用了一次operator int

大家可以在A(int n)中加一个cout<<"conventor construcor"的输出语句,再次看看效果。

class A{
public:
	int a;
	A(){};
	explicit A(int n){ this->a = n; } //与上面相比,加上了一个explicit
	operator int(){
		cout<<"use int conventor \n";
		return this->a;
	}
	operator=(const A a){
		this->a = a.a;
		return *this;
	}
};

int main(){
	A a, b, c(3);
	a = b = c;
	cout<<a.a<<endl;
	return 0;
}
无法通过编译:

error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'int' (or there is no acceptable conversion)

上面的例子中,说了会调用A(int n)这个“转换构造函数”,当给这个函数加上explicit时,就说明该构造函数只允许显示调用,而不能用于隐式的转换。

explicit A(int n){ .... },在声明类实例时:

A a = 3; \\错误

A a(3); \\正确

A a; a = 3; \\错误

所以,当遇到上面例子的 a=3这个过程时,就会因为找不到转换函数而报错!


关于类型转换和运算符重载其实挺迷惑人的,大家自己多动手写例子,慢慢推导体会!看几遍别人的推导分析,比不上自己一次的动手实验!



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值