目的:
有时候希望赋值运算符两边的类型可以不匹配
,比如,把一个int类型变量赋值给一个Complex对象,
或把一个 char * 类型的字符串赋值给一个字符串对象
,此时就需要重载赋值运算符“=”。
注意:赋值运算符“=”只能重载为成员函数
赋值运算符重载实例示例:
#include <iostream>
#include <string.h>
using namespace std;
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( ) { delete [] str; } //String类的析构函数
};
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!
*/
浅拷贝和深拷贝:
String S1, S2; //S1,S2为String类的对象。
S1 = “this”; //已经定义了 这种赋值的重载(如上面的程序)
S2 = “that”;
S1 = S2; //将调用String类的默认复制构造函数。
浅拷贝:
导致“指针悬挂“问题
如果我们没有两个对象间,定义赋值运算符的重载,执行S1=S2;会导致许多隐藏的问题。(浅拷贝)
下面是我们的执行过程(没有定义赋值运算符);
1:对两个对象进行
2:执行S1 = S2后。
注:如不定义自己的赋值运算符,那么S1=S2实际上导致 S1.str和 S2.str指向同一地方。
导致问题:
- 如果S1对象消亡,析构函数将释放 S1.str指向的空间,则S2消亡时还要释放一次,不妥。
- 如果执行 S1 = “other”;会导致S2.str指向的地方被delete
解决方法:在class String里添加成员函数:。
深拷贝:
为了解决浅拷贝出现的错误,必须显式地定义一个自己的赋值运算符,使之不但赋值数据成员,而且为对象 p1 和 p2 分配了各自的内存空间,这就是深拷贝。
String & operator = (const String & s) {
delete [] str;
str = new char[strlen( s.str)+1];
strcpy( str,s.str);
return * this;
}
修改示例:
#include <iostream>
#include <string.h>
using namespace std;
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 & operator = (const String & s) {
delete [] str;
str = new char[strlen( s.str)+1];
strcpy( str,s.str);
return * this;
}
};
int main()
{
String S1, S2;
S1 = "this";
S2 = "that";
cout << S1.c_str() << endl;
cout << S2.c_str() << endl;
S1 = S2;
cout << S1.c_str() << endl;
cout << S2.c_str() << endl;
return 0;
}
/*
输出结果:
this
that
that
that
*/
讨论:对 operator = 返回值类型的讨论
void 好不好?String 好不好? 为什么是 String &
1:对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性
String & operator = (const char * s){
delete [] str;
str = new char[strlen(s)+1];
strcpy( str, s);
return * this;
}
补充:String类编写复制构造函数的时候,会面临和 = 同样的问题,用同样的方法处理。
某些时候会自动调用复制构造函数会产生一些临时对象,这些对象在析构函数中被释放时会空间,那么就可能导致指针悬挂问题。
解决方法:重写复制构造函数
String( String & s)
{
str = new char[strlen(s.str)+1];
strcpy(str,s.str);
}