实现运算符重载有两种形式:重载为成员函数、重载为友元函数。
#include<iostream>
using namespace std;
class Complex
{
public:
Complex()
{
real = 0;
imag = 0;
}
Complex(double r,double i)
{
real = r;
imag = i;
}
Complex(const Complex& rhs)
{
real = rhs.real;
imag = rhs.imag;
}
//Complex& operator+(const Complex& rhs);//重载为成员函数
friend Complex operator+(Complex& lhs,Complex &rhs);//重载为友元函数
//Complex& operator-(const Complex& rhs);
friend Complex operator-(Complex& lhs,Complex &rhs);
//Complex& operator*(const Complex& rhs);
friend Complex operator*(Complex& lhs,Complex &rhs);
//Complex& operator/(const Complex& rhs);
friend Complex operator/(Complex& lhs,Complex &rhs);
void show()
{
cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
private:
double real;//实部
double imag;//虚部
};
Complex operator+(Complex& lhs,Complex &rhs)
{
return Complex(lhs.real+rhs.real,lhs.imag+rhs.imag);
}
Complex operator-(Complex& lhs,Complex &rhs)
{
return Complex(lhs.real-rhs.real,lhs.imag-rhs.imag);
}
Complex operator*(Complex& lhs,Complex &rhs)
{
return Complex(lhs.real*rhs.real-lhs.imag*rhs.imag,lhs.imag*rhs.real + lhs.real*rhs.imag);
}
Complex operator/(Complex& lhs,Complex &rhs)
{
double r = (lhs.real*rhs.real+lhs.imag*rhs.imag)/(rhs.real*rhs.real+rhs.imag*rhs.imag);
double i = (lhs.imag*rhs.real - lhs.real*rhs.imag)/(rhs.real*rhs.real+rhs.imag*rhs.imag);
return Complex(r,i);
}
/*
Complex& Complex::operator+(const Complex& rhs)
{
Complex tmp;
tmp.real = real + rhs.real;
tmp.imag = imag + rhs.imag;
return tmp;
}
Complex& Complex::operator-(const Complex& rhs)
{
Complex tmp;
tmp.real = real - rhs.real;
tmp.imag = imag - rhs.imag;
return tmp;
}
Complex& Complex::operator*(const Complex& rhs)
{
Complex tmp;
tmp.real = real*rhs.real-imag*rhs.imag;
tmp.imag = imag*rhs.real + real*rhs.imag;
return tmp;
}
Complex& Complex::operator/(const Complex& rhs)
{
Complex tmp;
tmp.real = (real*rhs.real+imag*rhs.imag)/(rhs.real*rhs.real+rhs.imag*rhs.imag);
tmp.imag = (imag*rhs.real - real*rhs.imag)/(rhs.real*rhs.real+rhs.imag*rhs.imag);
return tmp;
}
*/
int main()
{
Complex c1(3,4),c2(5,-10),c3; //定义三个复数对象
cout<<"c1=";
c1.show();
cout<<"c2=";
c2.show();
c3=c1+c2;
cout<<"c1+c2=";
c3.show();
c3=c1-c2;
cout<<"c1-c2=";
c3.show();
c3=c1*c2;
cout<<"c1*c2=";
c3.show();
c3=c1/c2;
cout<<"c1/c2=";
c3.show();
return 0;
}
重载为成员函数 与重载为友元函数的区别:
重载为成员函数时,形参个数=原本的操作数-1。(因为隐含this指针);
重载为友元函数时,形参个数=原本的操作数。
什么时候重载为成员函数?什么时候重载为友元函数?
1、赋值(=)、下标([])、调用(())和成员访问箭头(->)等操作符必须定义为成员,将这些操作符定义为非成员函数将在编译时标记为错误。
2、像赋值一样,复合赋值操作符通常应定义为类的成员函数,与赋值不同的是,不一定非得这样做,如果定义非成员复合赋值操作符,不会出现编译错误。
3、改变对象状态或与给定类型紧密联系的其他一些操作符, 如自增、自减和解引用,通常就定义为类成员。
4、对称的操作符,如算术操作符、相等操作符、关系操作符最好定义为友元函数。
5、>>、<<操作符定义为友元函数。
运算符 + 与 += 的重载的区别与联系:
1、operator+ 通常定义成非成员,operator+=通常定义成成员
2、operator+= 返回操作数的引用,而operator+返回一个临时对象
3、通常我们用 operator += 来实现 operator+
其它算术操作符(+,-,*,/,%)同+
class Complex
{
public:
Complex()
{
real = 0;
imag = 0;
}
Complex(double r,double i)
{
real = r;
imag = i;
}
Complex(const Complex& rhs)
{
real = rhs.real;
imag = rhs.imag;
}
Complex& operator+=(const Complex& rhs);
friend Complex operator+(Complex& lhs,Complex &rhs);
Complex& operator-=(const Complex& rhs);
friend Complex operator-(Complex& lhs,Complex &rhs);
Complex& operator*=(const Complex& rhs);
friend Complex operator*(Complex& lhs,Complex &rhs);
Complex& operator/=(const Complex& rhs);
friend Complex operator/(Complex& lhs,Complex &rhs);
void show()
{
cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
private:
double real;
double imag;
};
Complex& Complex::operator+=(const Complex& rhs)
{
real+=rhs.real;
imag+=rhs.imag;
return *this;
}
Complex operator+(Complex& lhs,Complex &rhs)
{
Complex c(lhs);
c+=rhs;
return c;
}
Complex& Complex::operator-=(const Complex& rhs)
{
real-=rhs.real;
imag-=rhs.imag;
return *this;
}
Complex operator-(Complex& lhs,Complex &rhs)
{
Complex c(lhs);
c-=rhs;
return c;
}
Complex& Complex::operator*=(const Complex& rhs)
{
double r = real*rhs.real-imag*rhs.imag;
double i = imag*rhs.real + real*rhs.imag;
real = r;
imag = i;
return *this;
}
Complex operator*(Complex& lhs,Complex &rhs)
{
Complex c(lhs);
c*=rhs;
return c;
}
Complex& Complex::operator/=(const Complex& rhs)
{
double r = (real*rhs.real+imag*rhs.imag)/(rhs.real*rhs.real+rhs.imag*rhs.imag);
double i = (imag*rhs.real - real*rhs.imag)/(rhs.real*rhs.real+rhs.imag*rhs.imag);
real = r;
imag = i;
return *this;
}
Complex operator/(Complex& lhs,Complex &rhs)
{
Complex c(lhs);
c/=rhs;
return c;
}
int main()
{
Complex c1(3,4),c2(5,-10),c3; //定义三个复数对象
cout<<"c1=";
c1.show();
cout<<"c2=";
c2.show();
c3=c1+c2;
cout<<"c1+c2=";
c3.show();
c3=c1-c2;
cout<<"c1-c2=";
c3.show();
c3=c1*c2;
cout<<"c1*c2=";
c3.show();
c3=c1/c2;
cout<<"c1/c2=";
c3.show();
return 0;
}
根据复合赋值操作符(如+=)来实现算数操作符(如+),比其他方式更简单更有效。调用+=来实现+则可以不必创建和撤销一个临时量来保存+的结果。
输出(<<)、输入(>>)操作符重载
ostream& operator<<(ostream& out,const Complex& rhs)
{
cout<<"("<<rhs.real<<","<<rhs.imag<<"i)"<< endl;
return out;
}
istream& operator>>(istream& in,Complex& rhs)
{
cout << "operator>>" << endl;
double r;
double i;
in >> r >> i;
if(in)
{
rhs.real = r;
rhs.imag = i;
}
else
{
rhs = Complex();
}
return in;
}
输出运算符重载第一个形参是对ostream对象的引用,在该对象上将产生输出。该形参是引用,因为不能复制ostream对象。
第二个参数一般是对要输出的类类型的引用。输出不应该改变对象的值,所以加const。使形参为const引用还有一个好处就是可以使用同一个定义来输出const和非const对象。
返回ostream的引用,它通常是输出操作符所操作的ostream对象。
I/O操作符重载函数必须为非成员函数。如果定义为成员函数,左操作数只能是该类型的对象。使用时如下:Complexc;c << cout;这个用法与为其他类型定义的输出操作符的正常使用方式相反。左操作数必须为ostream类型,这意味着如果该操作符是类的成员,它必须是ostream类的成员,然而,ostream类是标准库的组成部分,不能为标准库中的类增加成员。所以I/O操作符重载要写成非成员函数。通常对非公有数据成员进行读写,因此类通常将IO操作设为友元。
与输出操作符类似,输入操作符的第一个形参是一个引用,指向它要读的流,并返回的也是对同一个流的引用。第二个形参必须为非引用,因为输入一定会改变该对象。输入和输出不同的是:输入操作符必须处理错误和文件结束的可能性。