1. 基本概念:(1)运算符重载就是对已有的运算符(C++中预定义的运算符)赋予多重的含义,使同一运算符作用于不同类型数据时导致不同类型的行为。
(2)目的:扩展C++中提供的运算符的适用范围,使之能作用于对象。
(3)同一运算符,对不同类型的操作数,所发生的行为不同。如: 复数相加生成新的复数对象 complex_a + complex_b
2. 运算符重载的形式:
(1)运算符重载的实质就是函数重载
(2)可以重载为普通函数,也可以重载为成员函数
(3)把含运算符表达式转换成对运算符函数的调用
(4)把运算符的操作数转换成运算符函数的参数
(5)运算符可以被多次重载,根据实参类型决定调用哪个运算符函数
返回值类型 operator 运算符(形参表)
{
......
}
譬如示例:
class Complex
{
public:
double real, imag;
Complex (double r = 0.0, double i = 0.0):real(r),imag(i){}
Complex operator-(const Complex & c);
};
Complex operator+( const Complex & a, const Complex & b)
{
return Complex( a.real + b.real, a.imag + b.imag);
}
Complex Complex:: operator-(const Complex & c)
{
return Complex (real - c.real, imag - c.imag);
}
//备注:重载为成员函数时,参数个数为运算符操作数数目减一。
// 重载为普通函数时,参数个数就是运算符操作数数目。
int main()
{
Complex a(4, 4), b(1, 1);
//c = a + b; // 等价于 c=operator+(a,b);
c = operator+(a,b);
cout << "(" << c.real << "," << c.imag << ")" << endl;
cout << "(" <<a.operator-(b).real<< "," << (a-b).imag << ")" << endl;
// a-b等价于a.operator-(b);
//std::cout << "Hello World!\n";
}
3. 赋值运算符重载
(1)赋值运算符只能重载为成员函数
(2)示例
#include<string.h>
#pragma warning(disable:4996)
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::operator = (const char* s)
{
if( this == &s) // 防止出现 s = s; 这种情况
return * this;
// 重载“=”以使得 obj = "hello" 能够成立
delete[] str; // 将原始的动态内存清除,在下面进行重新分配动态内存,+1是为了存放'/0'
str = new char[strlen(s) + 1];
strcpy(str, s);
return *this;
}
int main()
{
String s;
s = "good luck";
cout << s.c_str() << endl;
// String s2 = "hello!"; // 这条语句是初始化语句,如果想成功运行需要在构造函数里支持字符串参数的输入进行初始化。
s = "shenzhou 8!";
cout << s.c_str() << endl;
return 0;
}
4. 对operator = 返回值类型的讨论
提出: void 好不好?
String 好不好?
为什么是 String &
对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性
考虑: a = b = c; // 此时如果返回值是 void 那么就会出现类型不匹配
(a = b) = c; // 会修改a的值,因为在C++里面赋值运算符的返回值就是等号左边值的引用,此时b的值不变
5. String类还要注意的问题
为 String类编写复制构造函数的时候,会面临和 = 同样的问题,用同样的方法处理。
重写复制构造函数
String ( String & s)
{
str = new char[strlen(s.str)+1];
strcpy(str,s.str);
}
6. 运算符重载为友元函数
(1)一般情况下,将运算符重载为类的成员函数,是较好的选择。
(2)但有时,重载为成员函数不能满足使用要求,重载为普通函数,又不能访问类的私有成员,所以需要将运算符重载为友元。
如:我们一般可以算 c = a + 5; 但不能算 c = 5 + c;
Complex operator +(double r,const Complex & c) // 此为普通函数
{
return Complex (c.real + r, c.imag);
}
friend Complex operator +(double r, const Complex & c);