1、复数类 应具有的操作
1.1、
运算:+、-、*、/
1.2、
比较:==、!=
1.3、
赋值:=
1.4、
求模:modulus
2、 利用操作符重载
2.1、统一复数与实数的运算方式
Complex operator + (const Complex& c);//因为对象的this关键字的缘故,省去一个参数
Complex
operator
- (
const
Complex&
c);
Complex
operator
* (
const
Complex&
c);
Complex
operator
/ (
const
Complex&
c);
Complex
&
operator
= (
const
Complex& c);
//
赋值
2.2、统一复数与实数的比较方式
bool
operator
== (
const
Complex&
c);
bool
operator
!= (
const
Complex& c);
见文件中的代码:Complex
/**************** 成员函数重载操作符 *************/
#include <stdio.h>
class Complex
{
private:
int a;
int b;
public:
Complex(int a = 0, int b = 0)
{
this->a = a;//普通函数是具有this参数的,静态函数没有。初始化每个对象的成员变量。
this->b = b;
}
int getA()
{
return a;
}
int getB()
{
return b;
}
//方式一: 通过全局普通的函数实现复数相加 ,,为了在外部访问类中私有成员,用友元声明。
friend Complex Add(const Complex& p1, const Complex& p2);//这个函数是这个类的友元函数
//方式二:通过全局函数重载“+”操作符实现复数相加,
friend Complex operator + (const Complex& p1, const Complex& p2);
//方式三:通过成员函数实现 “+” 操作符的重载
Complex operator+(const Complex& p) //参数少了一个左操作数!因为普通成员函数有this指针关键字。
{
Complex ret;
ret.a = this->a + p.a; //this ->a 是对象里面的数据。
ret.b = this->b + p.b;
return ret;
}
};
//全局普通函数
Complex Add(const Complex& p1, const Complex& p2)
{
Complex ret;
ret.a = p1.a + p2.a; //因为是友元函数,所以可以直接访问
ret.b = p1.b + p2.b;
return ret;
}
//全局重载操作符 + ,,重载的实质就是为了扩展函数功能
Complex operator + (const Complex& p1, const Complex& p2)
{
Complex ret;
ret.a = p1.a + p2.a;
ret.b = p1.b + p2.b;
return ret;
}
int main()
{
Complex c1(1, 2); //使用对象来初始化,调用构造函数。
Complex c2(3, 4);
//方式一的调用
//Complex c3 = Add(c1, c2); //函数实现复数的计算,缺点:无法写成c1 + c2的形式。
//方式二的调用
//Complex c3 = operator+(c1, c2); //把“opertor”当成函数名一样的调用。
//Complex c3 = c1 + c2; //更加直观,但是本质上还是调用"operator+"这个函数。
//方式三的调用
Complex c3 = c1.operator+(c2); //把“operator + ”当成函数名一样的调用,c1对象的函数。
//Complex c3 = c1 + c2; //优先选择成员函数,而不是全局的opertor+ 函数。
printf("c3.a = %d, c3.b = %d\n", c3.getA(), c3.getB());
return 0;
}
/*********** 复数类的完善 *********/
#include <stdio.h>
#include <math.h>
class Complex
{
private:
double a; //定义变量时,默认就是private
double b;
public:
Complex(double a = 0, double b = 0);
double getA();
double getB();
double getModulus();
Complex operator + (const Complex& c);
Complex operator - (const Complex& c);
Complex operator * (const Complex& c);
Complex operator / (const Complex& c);
bool operator == (const Complex& c);
bool operator != (const Complex& c);
Complex& operator = (const Complex& c); //返回对象的引用
};
//在声明的类外面定义函数
Complex::Complex(double a, double b)
{
this->a = a;
this->b = b; //this 指代调用这个函数的对象。
}
double Complex::getA()
{
return a;
}
double Complex::getB()
{
return b;
}
double Complex::getModulus()
{
return sqrt(a*a + b*b);
}
Complex Complex::operator + (const Complex& c)
{
double na = this->a + c.a; //在类中直接使用
double nb = this->b + c.b; //将a 和 b添加上 this关键字。少一个左操作数。
return Complex(na, nb);
}
Complex Complex::operator - (const Complex& c)
{
double na = a - c.a; //在类中直接使用
double nb = b - c.b;
return Complex(na, nb);
}
Complex Complex::operator * (const Complex& c)
{
double na = a * c.a - b * c.b; //在类中直接使用
double nb = a * c.b - b * c.a;
return Complex(na, nb);
}
Complex Complex::operator / (const Complex& c)
{
double cm = c.a * c.a + c.b * c.b;
double na = (a * c.a + b * c.b) / cm;
double nb = (b * c.a - a * c.b) / cm;
return Complex(na, nb);
}
bool Complex::operator == (const Complex& c)
{
return (a == c.a) && (b == c.b);
}
bool Complex::operator != (const Complex& c)
{
//整个复数对象就两个成员,如果这2个对象的内存完全相等时,则两个复数相等。
//判断两个对象是否一致
return !(*this == c); //等下改成this 和 &c 试试//可以的,两个地址相同。
}
Complex& Complex::operator = (const Complex& c)
{
if(this != &c) //判断两个地址是否相同。避免自赋值。
{
this->a = c.a;
this->b = c.b;
}
return *this; //返回对象的引用。
}
int main()
{
Complex c1(1, 2);
Complex c2(3, 6); //多调用一次构造函数。
Complex c3 = c2 - c1; //其实本质上还是通过函数调用的。c3 = c2.operator-(c1);
Complex c4 = c1 * c3;
Complex c5 = c2 / c1;//其实本质上还是通过函数调用的。c5 = c2.operator/(c1);
printf("\n");
printf("c3.a = %f, c3.b = %f\n",c3.getA(), c3.getB());//2, 4
printf("c4.a = %f, c4.b = %f\n",c4.getA(), c4.getB());//-6, 0
printf("c5.a = %f, c5.b = %f\n",c5.getA(), c5.getB());//3, 0
printf("\n");
Complex c6(2, 4);
printf("c3 == c6 为 %d\n", c3 == c6); //1
printf("c3 != c4: %d\n", c3 != c4); //1
printf("\n");
printf("before ;; c3.a = %f, c3.b = %f\n",c3.getA(), c3.getB());//2, 4
(c3 = c2) = c1;//赋值操作赋返回值是引用,可以连续赋值,如果返回对象,那么对象的生命周期只在这一行有效
//c2赋给c3,然后c1再赋给c3、
printf("c1.a = %f, c1.b = %f\n",c1.getA(), c1.getB());//1, 2
printf("c2.a = %f, c2.b = %f\n",c2.getA(), c2.getB());//3, 6
printf("c3.a = %f, c3.b = %f\n",c3.getA(), c3.getB());//1, 2
return 0;
}
3、注意事项
3.1、C++规定赋值操作符(=)只能重载为成员函数(而不能是全局函数)
3.2、操作符重载改变不了原操作符的优先级
3.3、操作符重载不能改变操作数的个数
3.4、操作符重载不应改变操作符的原有语义
4、小结
4.1、复数的概念可以通过自定义类实现
4.2、复数中的运算操作可以通过操作符重载实现
4.3、赋值操作符只能通过成员函数实现
4.4、操作符重载的本质为函数定义