C++语言利用函数重载和运算符重载完成复数运算

1.重载是什么?

教材上和网上讲的很多都晦涩难懂。用我自己的话来讲:
C++对函数和运算符可以有多个定义,类似于一词多义。分别称为函数重载运算符重载
你可以利用这个名称相同的函数或者相同的运算符实现不同的作用。

(1).在C++中的函数重载

在相同的一个作用域内,可以有一组具有相同名称的函数名,不同参数列表的函数。他们功能类似,但是他们内部的形式参数必须不一样。我们称这组函数为重载函数
作用:我们这样做可以减少函数名的数量,避免了名字空间的污染。对于程序的可读性有很大好处。

(2).在C++中的运算符重载

在C++语言程序里,我们可以重定义和重载很多的内置运算符,我可以通过重载实现自定义的功能。重载运算符要有特殊名称的函数。这里我们就有个新的关键词operator 。运算符重载要有关键词operator和要重载的运算符符号组成,并且需要一个返回类型和一个参数列表。如下所示:

ComplexNumber operator+(ComplexNumber z);

当然也有一些运算符在C++里定义不可被重载
下面是不可重载的运算符列表:

不可重载的运算符声明
.成员访问运算符
.* 和 ->*成员指针访问运算符
::域运算符
sizeof长度运算符
?:条件运算符
#预处理符号

2.复数的相关知识(部分)

(1).复数的定义和概念

复数是以a + bi的形式表示的数字,其中a和b是实数,而i可以说是方程x^2 = -1的解。因为没有实数满足该方程,所以称为虚数。对于复数a + bi,a称为实部b称为虚部。尽管有历史术语“虚构”,但复数在数学科学中被视为与实数一样“实”,并且在自然界科学描述的许多方面都是基础。

复数与其他数之间的关系

复数可以求解某些方程式,而这些方程式没有实数解。
例如,等式 (x+1)^2 = -9
这个等式没有实数解,因为实数的平方不能为负。可是复数提供了解决此问题的方法。是用满足关系 i 的平方 = -1的不确定的 i(有时称为虚数单位)扩展实数,以便可以找到类似于上一个方程的方程式的解。在这种情况下,解为-1 + 3i和 -1 - 3i 。

(2).复数的几何意义

在几何上,复数通过将水平轴用于实部,将垂直轴用于虚部,将一维 数线的概念扩展到二维 复平面。复数a + bi可以用复平面中的点(a,  b)来标识。实数为零的复数被称为纯虚数; 这些数字的点位于复平面的垂直轴上。虚部为零的复数可以看作是实数;它的点位于复杂平面的水平轴上。复数也可以以极坐标形式表示,它会将每个复数与其到原点的距离(其大小)和一个特定角度(称为该复数的自变量)相关联。
复数几何表示
复数可以在视觉上表示为一对数字(a,  b),在Argand图上形成矢量,表示复数平面。“ Re”是实轴,“ Im”是虚轴,并且 i 满足 i^2 = -1
可知:
1.复数z=a+bi 与复平面内的点(a,b)一一对应
2.复数z=a+bi 与向量OZ一一对应,其中Z点坐标为(a,b)

(3).复数代数形式的加减法运算

两个复数相加法则
  ( x + y i ) + ( u + v i ) = ( x + u ) + ( y + v ) i \ (x+yi)+(u+vi)=(x+u)+(y+v)i  (x+yi)+(u+vi)=(x+u)+(y+v)i
两个复数相减法则:
  ( x + y i ) − ( u + v i ) = ( x − u ) + ( y − v ) i \ (x+yi)-(u+vi)=(x-u)+(y-v)i  (x+yi)(u+vi)=(xu)+(yv)i

当然我们也可以通过几何形式来理解复数的加减法运算。我们可以通过构造平行四边形可以在几何上完成两个复数的加法。使用复数平面的的可视化:两个复数之和 ab 为复平面中的点,是通过从三个顶点构建平行四边形获得的点O,并标记箭头的点a 和 点b(前提是他们不在一条线上)。等效地,称这些点 A,B分别和平行四边形的第四点 X,该三角形 OABXBA 是相同的。减法的可视化可以通过考虑另外的负面来实现减数。
复数加法 几何表示

(4).复数的乘除法运算

复数的乘法法则:

  ( x + y i ) ∗ ( u + v i ) = ( x u − y v ) + ( x v + y u ) i \ (x+yi)*(u+vi)=(xu-yv)+(xv+yu)i  (x+yi)(u+vi)=(xuyv)+(xv+yu)i

复数的除法法则:
这里需要用到共轭复数 即两个实部相等,虚部互为相反数的复数互为共轭复数。当虚部不为零时,共轭复数就是实部相等,虚部相反,如果虚部为零,其共轭复数就是自身,当虚部不等于0时也叫共轭虚数。复数z的共轭复数记作z(上加一横,我打不出来这个字如果有人知道怎么用Markdown编辑器写出来可以教教我),有时也可表示为Z*。同时, 复数z(上加一横)称为复数z的复共轭
关于非零复数的倒数计算:
非零复数倒数计算
这可以用来表示任意复数的除法(z不等于0)
复数除法法则

3.C++中的友元函数

友元函数就是指不是类成员的函数,但它可以访问类的所有成员。可以这么理解类授予了友元函数一种特权,使友元函数可以轻松访问并利用所有私有和保护成员
当然友元这个概念可以是函数也可以是类。我们叫它友元函数友元类。友元类咱们的项目目前不用,这次不仔细分析了。
作用:如果你是个开发者,你在库里看见了一个其他人的项目,你想练练手。很多情况下你是无法访问到代码的私有成员和保护成员。如果在类里函数有友元函数,这就说明可以在这个友元函数里访问私有成员和保护成员。
关键词:friend
如果要声明函数为一个类的友元,需要在类定义中该函数使用关键字 friend, 如下所示:

friend ComplexNumber operator+(const float a, const ComplexNumber &z);

4.思路和设计

(1).程序组成和思路

对于程序的思路,我先写了一个复数的类。在类里的私有成员我利用双精度浮点数来定义了实部和虚部。在公有成员里我将会重载自身函数。讲实部和虚部能输入系统里。这里我讨论了三种情况:实部和虚部输入都意义;不输入实部和虚部;只输入虚部。并且我将实部和虚部的初始化值为0.
在共有成员里还写了一个实部虚部相加的函数,用来实现实部和虚部的储存与转换。并且写了设置的函数同理。接着就是程序输出的函数:内部我写了个判断语句用来判断虚部是否大于等于0.最后就是将四个运算和输入输出运算符重载的函数。我将加法分两种情况重载。(用类模板之类的就另一回事了,我这里就函数和运算符重载),我会将输入和输出还有加法设置为友元函数使其可以直接访问私有成员。最后在类外写一个测试用的函数语句。在主函数上调用就可以了。

(2).部分函数对应源代码的作用

输出时判断虚部是否大于等于0,防止出现负负之类的情况:

void ComplexNumber::Show()
{
	if(im>=0)
	cout <<"("<< re << "+" << im <<"i)";
	else
	cout <<"("<< setiosflags(ios::fixed) << setprecision(2) << re << "+" << im << "i" <<")";

};

复数乘法运算(乘号运算符的重载)的实现:

ComplexNumber ComplexNumber::operator *(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=re*z.re-(im*z.im);
	tmp.im=im*z.re+re*z.im;
	return tmp;
}

复数除法运算(除号运算符的重载)的实现:

ComplexNumber ComplexNumber::operator/(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=(re*z.re+im*z.im)/(z.re*z.re+z.im*z.im);
	tmp.im=(im*z.re-re*z.im)/(z.re*z.re+z.im*z.im);
	return tmp;
}

输出运算符的重载:

ostream & operator << (ostream & a,const ComplexNumber & z)
{
	if(z.re==0&&z.im==0)a << setiosflags(ios::fixed) << setprecision(0) << z.re;
	else if(z.im==0)a << setiosflags(ios::fixed) << setprecision(0) << z.re ;
	else if(z.im>0)
	a << setiosflags(ios::fixed) << setprecision(2) << z.re << "+" << z.im << "i";
	else if(z.im<0)
	a << setiosflags(ios::fixed) << setprecision(2) << z.re << z.im << "i";
	return a;
}

测试输入函数:

void CN() 
{ 
    //ComplexNumber
	ComplexNumber cn1, cn2;
	std::cin >> cn1 >> cn2;
	std::cout<<cn1+cn2 << std::endl;
	std::cout<<cn1 - cn2 << std::endl;
	std::cout<<cn1*cn2 << std::endl;
	std::cout<<cn1 / cn2 << std::endl;
}

(3).整体源代码

整体的源代码如下:

#include <iostream>
#include <iomanip>
using namespace std;
class ComplexNumber
{
private:
	double im,re;
public:
	ComplexNumber(double i=0, double r=0);
//	ComplexNumber();
//	ComplexNumber(int i);
    ComplexNumber Add(ComplexNumber z); 
    ComplexNumber operator+(ComplexNumber z);
    friend ComplexNumber operator+(const float a, const ComplexNumber &z);
    friend istream & operator >> (istream & b, ComplexNumber &z);
    friend ostream & operator << (ostream & a,const ComplexNumber & z);
    ComplexNumber operator-(ComplexNumber z);
    ComplexNumber operator*(ComplexNumber z);
    ComplexNumber operator/(ComplexNumber z);
    double Set(double x, double y);
	void Show();
	
};
ComplexNumber::ComplexNumber(double i, double r)
{
	im=r;
	re=i;
}
/*ComplexNumber::ComplexNumber()
{
	im=0;
	re=0;
} 
ComplexNumber::ComplexNumber(int i)
{
	im=i;
	re=0;
}*/ 

void ComplexNumber::Show()
{
	if(im>=0)
	cout <<"("<< re << "+" << im <<"i)";
	else
	cout <<"("<< setiosflags(ios::fixed) << setprecision(2) << re << "+" << im << "i" <<")";

};
ComplexNumber ComplexNumber::Add(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=re+z.re;
	tmp.im=im+z.im;
	return tmp;
}
ComplexNumber ComplexNumber::operator +(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=re+z.re;
	tmp.im=im+z.im;
	return tmp;
}
ComplexNumber operator +(const float a,const ComplexNumber &z)
{
	ComplexNumber tmp;
	tmp.re=a+z.re;
	tmp.im=z.im;
	return tmp;
}
ComplexNumber ComplexNumber::operator -(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=re-z.re;
	tmp.im=im-z.im;
	return tmp;
}
ComplexNumber ComplexNumber::operator *(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=re*z.re-(im*z.im);
	tmp.im=im*z.re+re*z.im;
	return tmp;
}
ComplexNumber ComplexNumber::operator/(ComplexNumber z)
{
	ComplexNumber tmp;
	tmp.re=(re*z.re+im*z.im)/(z.re*z.re+z.im*z.im);
	tmp.im=(im*z.re-re*z.im)/(z.re*z.re+z.im*z.im);
	return tmp;
}
double ComplexNumber::Set(double x, double y)
{
	im=y;
	re=x;
	return im,re;
}
istream & operator>>(istream & b, ComplexNumber &z)
{
	b >> z.re >> z.im;
	return b;
}
ostream & operator << (ostream & a,const ComplexNumber & z)
{
	if(z.re==0&&z.im==0)a << setiosflags(ios::fixed) << setprecision(0) << z.re;
	else if(z.im==0)a << setiosflags(ios::fixed) << setprecision(0) << z.re ;
	else if(z.im>0)
	a << setiosflags(ios::fixed) << setprecision(2) << z.re << "+" << z.im << "i";
	else if(z.im<0)
	a << setiosflags(ios::fixed) << setprecision(2) << z.re << z.im << "i";
	return a;
}

void CN() 
{ 
    //ComplexNumber
	ComplexNumber cn1, cn2;
	std::cin >> cn1 >> cn2;
	std::cout<<cn1+cn2 << std::endl;
	std::cout<<cn1 - cn2 << std::endl;
	std::cout<<cn1*cn2 << std::endl;
	std::cout<<cn1 / cn2 << std::endl;
}
int main(void) 
{
	CN();
	return 0;
}

到此关于“C++语言利用函数重载和运算符重载完成复数运算”就成功实现了,谢谢大家的阅读。
这部分算是我的学习笔记,在CSDN平台发表希望可以帮助更多人们。如有问题我定会加以改正,非常感谢大家的意见和建议。

版权声明
本文被以下参考引用内容外均为J0hn原创内容,最终解释权归原作者所有。如有侵权,请联系删除。未经本人授权,请勿私自转载!

5.参考资料

[1]. CppReference https://en.cppreference.com/w/cpp/language/operators
[2]. GeeksForGeeks https://www.geeksforgeeks.org/function-overloading-c/
[3]. Wikipedia https://en.wikipedia.org/wiki/Complex_number#Addition_and_subtraction
[4]. Runoob https://www.runoob.com/cplusplus/cpp-overloading.html
[5]. Runoob https://www.runoob.com/cplusplus/cpp-friend-functions.html
[6]. 360Doc http://www.360doc.com/content/19/0118/12/46601607_809660209.shtml

  • 4
    点赞
  • 17
    收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论 2

打赏作者

J0hn

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值