原创 中国大学MOOC程序设计与算法(三):C++ 面向对象程序设计 第四周 运算符重载 笔记 之 赋值运算符的重载

第四周 运算符重载
1.运算符重载的基本概念
2.赋值运算符的重载
3.运算符重载为友元函数
4.运算符重载实例:可变长数组类的实现
5.流插入运算符和流提取运算符的重载
6.类型转换运算符、自增自减运算符的重载

2.赋值运算符的重载

有时候希望赋值运算符两边的类型可以不匹配,比如,把一个int类型变量赋值给一个Complex对象,或把一个 char * 类型的字符串赋值给一个字符串对象,此时就需要重载赋值运算符“=”。

赋值运算符“=”只能重载为成员函数

例子:

class String {
	private:
		char * str;
	public:
		String ():str(new char[1]) { str[0] = 0;}
		const char * c_str() { return str; };
		String & operator = (const char * s);
		String::~String( ) { delete [] str; }
};
String & String::operator = (const char * s)
{ 
	// 重载“=”得 以使得 obj = “hello” 能够成立
	delete [] str;
	str = new char[strlen(s)+1];
	strcpy( str, s);
	return * this;
}
int main()
{
	String s;
	s = "Good Luck," ; //于 等价于 s.operator=("Good Luck,");
	cout << s.c_str() << endl;
	// String s2 = "hello!"; // 这条语句要是不注释掉就会出错,因为这里不是赋值语句而是初始化语句,调用的不是重载的赋值符号而是构造函数,这里没有定义相应的构造函数
	s = "Shenzhou 8!"; //于 等价于 s.operator=("Shenzhou 8!");
	cout << s.c_str() << endl;
	return 0;
}
输出:
Good Luck,
Shenzhou 8!

浅拷贝和深拷贝

class String {
	private:
		char * str;
	public:
		String ():str(new char[1]) { str[0] = 0;}
		const char * c_str() { return str; };
		String & operator = (const char * s){
			delete [] str;
			str = new char[strlen(s)+1];
			strcpy( str, s);
			return * this;
		};
		~String( ) { delete [] str; }
};

String S1, S2;
S1 =this;
S2 = “that”;
S1 = S2;

如果不定义自己的赋值运算符:
结果是那么S1=S2实际上导致 S1.str和 S2.str指向同一地方。
在这里插入图片描述
这会产生以下几个后果
1) S1.str原来指向的地方被废弃,永远不会再被释放,成为内存垃圾;
2) 如果S1对象消亡,析构函数将释放 S1.str指向的空间,则S2消亡时还要释放一次,不妥,因为new出来的空间只能delete一次,程序崩溃。
3) 另外,如果执行 S1 = “other”;会导致S2.str指向的地方被delete。
因此要在 class String里添加成员函数:

String & operator = (const String & s) {
	delete [] str;
	str = new char[strlen( s.str)+1];
	strcpy( str,s.str);
	return * this;
}

这么做就够了吗?还有什么需要改进的地方?考虑下面语句:

String s;
s = "Hello";
s = s;//用自己赋值自己

问题:自己的内存已经先被释放了,然后访问就回出错
解决办法:

String & operator = (const String & s){
	if( this == & s)
		return * this;
	delete [] str;
	str = new char[strlen(s.str)+1];
	strcpy( str,s.str);
	return * this;
}

对 operator = 返回值类型的讨论
void 好不好?
String 好不好?
为什么是 String &
对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性
考虑: a = b = c;和 (a=b)=c; //会修改a的值
分别等价于:

a.operator=(b.operator=(c));
(a.operator=(b)).operator=(c);//(a=b)返回a的引用

上面的String类是否就没有问题了?
为 String类编写复制构造函数的时候,会面临和 = 同样的问题,用同样的方法处理。避免指向同一个空间

String( String & s)
{
	str = new char[strlen(s.str)+1];
	strcpy(str,s.str);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值