C++复数类运算符重载

实现运算符重载有两种形式:重载为成员函数、重载为友元函数。

#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操作符重载函数必须为非成员函数。如果定义为成员函数,左操作数只能是该类型的对象。使用时如下:Complexcc << cout;这个用法与为其他类型定义的输出操作符的正常使用方式相反。左操作数必须为ostream类型,这意味着如果该操作符是类的成员,它必须是ostream类的成员,然而,ostream类是标准库的组成部分,不能为标准库中的类增加成员。所以I/O操作符重载要写成非成员函数。通常对非公有数据成员进行读写,因此类通常将IO操作设为友元。

与输出操作符类似,输入操作符的第一个形参是一个引用,指向它要读的流,并返回的也是对同一个流的引用。第二个形参必须为非引用,因为输入一定会改变该对象。输入和输出不同的是:输入操作符必须处理错误和文件结束的可能性。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值