用的是vs2019编译器
这是一个有关运算符重载的例题,希望大家作以参考
定义有理数类(分母不为0的分数,分子分母均为整数)Rational,实现相应操作符的重载。
(1)定义私有数据成员:分子int iUp ; 分母int iDown。
(2)定义私有成员函数:void Reduce() 和 int Gcd(int l, int r),分别用于有理数的约简和求两个整数的最大公约数。其中,在约简时需要求取分子与分母的最大公约数。
(3)定义构造函数,在构造函数体内可调用Reduce对有理数进行约简。
(4)将负号-和赋值运算符=重载为公有成员函数,分别用于求有理数的负数和赋值。
(5)将前置++、前置–、后置++、后置–重载为公有成员函数,实现有理数自增1或自减1。
(6)将+、-、*、/重载为友员函数,实现有理数的加减乘除。
(7)将<、<=、>、>=重载为友员函数,实现有理数的大小关系比较。
(8)重载流插入符<<和流提取符>>,分别用于有理数的输出和输入。其中,输出格式为“分子/分母”,若为整数,则直接输出整数。
在main函数中,根据输入的分子和分母定义两个有理数对象a和b。再定义几个有理数对象分别用于表示a和b的加、减、乘、除、前置自增a、前置自减a、后置自增a、后置自减a,并依次各个对象的结果。最后依次用<、<=、>、>=比较a和b的大小关系,并依次输出比较结果(true或false)。
输入
两个有理数a和b的的分子和分母
输出
有理数a和b的加、减、乘、除以及前置自增a、前置自减a、后置自增a、后置自减a有理数a和b的<、<=、>、>=的结果
样例输入
4 3
3 2
样例输出
a+b: 17/6
a-b: -1/6
a*b: 2
a/b: 8/9
-a: -4/3
++a: 7/3
–a: 4/3
a++: 4/3
a–: 7/3
a<b: true
a<=b: true
a>b: false
a>=b: false
下面展示此题代码
#include <iostream>
using namespace std;class Rational{friend Rational operator+(Rational& p1, Rational& p2);friend Rational operator-(Rational& p1, Rational& p2);friend Rational operator*(Rational& p1, Rational& p2);friend Rational operator/(Rational& p1, Rational& p2);friend bool operator<(Rational& p1, Rational& p2);friend bool operator<=(Rational& p1, Rational& p2);friend bool operator>(Rational& p1, Rational& p2);friend bool operator>=(Rational& p1, Rational& p2);friend ostream& operator <<(ostream& cout, Rational& p);friend istream& operator >>(istream& cin, Rational& p);
private:int iUp;int iDown;//有理数约简void Reduce() {int t = abs(Gcd(iUp, iDown));iUp = iUp / t;iDown = iDown / t;if (iDown < 0){iDown = -iDown; iUp = -iUp; }}int Gcd(int l, int r) {int temp = l % r;while (temp != 0) {l = r;r = temp;temp = l % r;}return r;}public:Rational() {iUp = 1;iDown = 1;}Rational(int a,int b) {iUp = a;iDown = b;Reduce();}//相反数Rational operator-() { Rational temp;temp.iUp = -iUp;temp.iDown = iDown;return temp;}//赋值 Rational& operator=(const Rational& p) {iUp = p.iUp;iDown = p.iDown;Reduce();return *this;}//前置++Rational& operator++() {iUp += iDown;Reduce();return *this;}//前置--Rational& operator--() {iUp -= iDown;return *this;}//后置++Rational operator++(int) {Rational temp = *this;iUp += iDown;return temp;}//后置--Rational operator--(int) {Rational temp = *this;iUp -= iDown;return temp;} };
//加法+
Rational operator+(Rational& p1, Rational& p2) {Rational temp;temp.iDown = p1.iDown * p2.iDown;temp.iUp = p1.iUp * p2.iDown + p2.iUp * p1.iDown;temp.Reduce();return temp;
}
//减法-
Rational operator-(Rational& p1, Rational& p2) {Rational temp;temp.iDown = p1.iDown * p2.iDown;temp.iUp = p1.iUp * p2.iDown - p2.iUp * p1.iDown;temp.Reduce();return temp;
}
//乘法*
Rational operator*(Rational& p1, Rational& p2) {Rational temp;temp.iUp = p1.iUp * p2.iUp;temp.iDown = p1.iDown * p2.iDown;temp.Reduce();return temp;
}
//除法/
Rational operator/(Rational& p1, Rational& p2) {Rational temp;temp.iUp = p1.iUp * p2.iDown;temp.iDown = p1.iDown * p2.iUp;temp.Reduce();return temp;
}
//<号
bool operator<(Rational& p1, Rational& p2) {int temp;temp = p1.iDown * p2.iDown;p1.iDown = temp;p1.iUp += p2.iDown;p2.iDown = temp;p2.iUp += p1.iDown;p1.Reduce();p2.Reduce();if (p1.iUp < p2.iUp) {return true;}return false;
}
bool operator<=(Rational& p1, Rational& p2) {int temp;temp = p1.iDown * p2.iDown;p1.iDown = temp;p1.iUp += p2.iDown;p2.iDown = temp;p2.iUp += p1.iDown;p1.Reduce();p2.Reduce();if (p1.iUp <= p2.iUp) {return true;}return false;
}
bool operator>(Rational& p1, Rational& p2) {int temp;temp = p1.iDown * p2.iDown;p1.iDown = temp;p1.iUp += p2.iDown;p2.iDown = temp;p2.iUp += p1.iDown;p1.Reduce();p2.Reduce();if (p1.iUp > p2.iUp) {return true;}return false;
}
bool operator>=(Rational& p1, Rational& p2) {int temp;temp = p1.iDown * p2.iDown;p1.iDown = temp;p1.iUp += p2.iDown;p2.iDown = temp;p2.iUp += p1.iDown;p1.Reduce();p2.Reduce();if (p1.iUp >= p2.iUp) {return true;}return false;
}
ostream& operator <<(ostream& cout, Rational& p) {int temp;if (p.iUp % p.iDown == 0) {cout << p.iUp / p.iDown <<endl;}else {cout << p.iUp << "/" << p.iDown << endl;}return cout;
}
istream& operator >>(istream& cin, Rational& p) {cin >> p.iUp >> p.iDown;//cout << p.iUp << "/" << p.iDown << endl;return cin;
}int main()
{Rational a;Rational b;cin >> a;cin >> b;Rational c; c = a + b;cout << "a+b: " << c ;c = a - b;cout << "a-b: " << c;c = a * b;cout << "a*b: " << c;c = a / b;cout << "a/b: " << c;c = -a;cout << "-a: " << c ;cout << "++a: " << ++a ;cout << "--a: " << --a ;c = a++;cout << "a++: " << c ;c = a--;cout << "a--: " << c ;bool d;d = (a < b);cout << "a<b: " << boolalpha << d << endl;d = (a <= b);cout << "a<=b: " << boolalpha << d<< endl;d = (a > b);cout << "a>b: " << boolalpha << d << endl;d = (a >= b);cout << "a>=b: " << boolalpha << d << endl;system("pause");
}
对于这个题本人遇到的一些小问题
-
为什么在最后输出的时候引入了新的值c和d?
因为在重载<<和>>时,传入的是一个类对象的引用。例如,若直接写成
cout<<"a+b: "<< a + b << endl ;
则会造成重载的其实是a + b
这两个类对象的重载的加运算。 -
对于返回类类型的运算符重载来说,为什么有的返回的是类类型的引用?
以上代码在进行加减乘除时,都在重载函数内用了临时的类类型变量temp,所以如果用返回引用的话,编译器会报错,因为temp的生命周期只是在函数内,无法传它的引用到外界。而在前置++ ,赋值= 和 前置– 中,返回的是传入值的本身,所以要用引用返回。 -
关于
void Reduce()
函数在每一个二元运算中的调用。
调用的原因其实很简单,但是会很容易忽视。因为在二元运算后,可能会改变分子分母的符号,所以必须调用此函数,来调整输出,以保证如果是负数,输出时负号是在分子前面的,也可以调用此函数进行上下都是负数,从而约简成都是正数。