运算符重载
运算符重载
- 对已有的运算符赋予多重的含义
- 使同一运算符作用于不同类型的数据时有不同类型的行为
目的:
- 扩展cpp中提供的运算符的适用范围, 以用于类所表示的抽象数据类型
运算符重载的实质是函数重载,参数个数为运算符目数
返回值类型 operator 运算符(形参表)
{
……
}
在程序编译时:
- 把含运算符的表达式 -> 对运算符函数的调用
- 把运算符的操作数 -> 运算符函数的参数
- 运算符多次重载时,根据实参类型决定调用哪个运算符函数
- 运算符可以被重载为普通函数,也可以被重载为类的成员函数
例如复数相加:
重载为普通函数,参数个数为运算符目数
Complex operator+(const Complex &a, const Complex &b)
{
return Complex(a.real + b.real, a.imag + b.imag)
}
运算符重载为成员函数,参数个数为运算符目数减一
Complex operator+(const Complex &operand2);
// x = y + z
// 等价于 x = y.operator+(z)
赋值运算符重载
赋值运算符
赋值运算符两边的类型可以不匹配,但需要重载赋值运算符 =
- 把一个
int
类型变量 赋值给一个 Complex对象 - 把一个
char*
类型的字符串赋值给一个 字符串对象
注意:赋值运算符 =
只能重载为成员函数!
例子:字符串赋值
class String
{
private:
char *str;//指向动态分配的存储空间
public:
String() :str(NULL) {
}
const char *get_str() {
return str; }
char* operator=(const char *str);
~String();
};
char* String::operator=(const char *s)
{
//重载= -> obj="Hello"能够成立。调用时,把"Hello"的首地址传递进来
if (str)
{
delete[] str;
}
if (s)
{
str = new char[strlen(s) + 1];//+1是为了存放“/0”
strcpy(str, s);
}
else
{
str = NULL;
}
return str;
}
String::~String()
{
if (str)
{
delete[] str;
}
}
赋值运算符重载的目的:
- 可以使用其他类型变量或常量给对象赋值
- 解决浅拷贝的问题
浅复制与深复制
浅复制是一种逐字节的复制。在复制内容包含指针时会产生问题。
MyString S1, S2;
S1 = "this";
S2 = "that";
S2 = S1;
这样一个简单的程序会导致S1和S2的char *
变量指向同一块内存,会造成内存垃圾,以及重复delete
的隐患。
利用赋值运算符重载可以实现深复制:将一个对象中指针变量指向的内容,复制到另一个对象中指针成员对象指向的地方。
String& operator=(const String &s)
{
if (str == s.str) // 针对自身赋值的情况
{
return *this;
}
if (str)
{
delete[] str;
}
if (s.str)
{
str = new char[strlen(s.str