0
点赞
收藏
分享

微信扫一扫

【C++】运算符重载实现分数类的四则运算

兔八哥软件爱分享 2022-04-07 阅读 15

Fraction.h头文件代码:

#pragma once			
class Fraction {
private:
	int p;
	int q;
public:
	Fraction(int, int);		//构造函数声明
	int gcd(int, int)const;	//求最大公约数
	void Output();			//打印

	Fraction& operator++();		
		//前自增运算符重载,返回Fraction类引用
	Fraction operator++(int);	
		//后自增运算符重载,返回一个Fraction类对象。规定参数里必须加上int型。实际上并不起作用
	friend Fraction operator+(const Fraction& , const Fraction&);	
			//全局友元加法运算符重载函数。																
			//常引用(const Fraction&)是因为只需要对对象进行计算,不需要改变原对象的数据
	friend Fraction operator-(const Fraction&, const Fraction&);	
			//全局友元减法运算符重载函数
	friend Fraction operator*(const Fraction&, const Fraction&);	
			//全局友元乘法运算符重载函数
	friend Fraction operator/(const Fraction&, const Fraction&);	
			//全局友元除法运算符重载函数
};


下面是类的实现:(均放在main.cpp里,即声明和定义分开)

 gcd(greatest common divisor)函数实现:

用到了辗转相除法。可以参考辗转相除法 - unique_ptr - 博客园 (cnblogs.com)

int Fraction::gcd(int a, int b)const
{	//辗转相除法,返回最大公约数
	int r;
	while (b) {
		r = b;
		b = a % b;
		a = r;
	}
	return (a == 0 ? 1 : a);	
}

 构造函数实现

Fraction::Fraction(int m, int n) {
	int g = gcd(m, n);
	p = m / g;			//同时除以最大公约数
	q = n / g;
}

 后自增(x++)运算符重载:

Fraction Fraction::operator++(int) {	//后自增
	Fraction temp(*this);	//用默认拷贝构造函数,把当前对象保存在temp里
	p++;
	int g = gcd(p, q);
	p /= g;
	q /= g;
	return temp;
}

前自增(++x)运算符重载:

Fraction& Fraction::operator++() {		//前自增
	p++;
	int g = gcd(p, q);
	p /= g;
	q /= g;
	return *this;			//返回当前对象的引用
}

注意:

最重要的一点:前自增和后自增都是以“①类内定义非静态的成员函数”形式出现,而且参数列表为空,是因为成员函数自带一个this指针,这是隐性存在的。相当于我们有一个隐性的参数。

而我们下面要介绍的加减乘除的运算符重载都是以"②类外定义全局函数、类内声明成友元函数"形式出现,一般我们规定运算具有对称性的运算符往往采取②。实际上,无论是自增还是四则运算,都可以采用另外一种形式写。具体操作方法请读者自行思考,笔者受限于篇幅不赘述。

+运算符重载:

Fraction operator+(const Fraction& F1, const Fraction& F2) {
	Fraction temp(0, 0);
	temp.q = F1.q * F2.q;
	temp.p = F1.q * F2.p + F2.q * F1.p;
	int g = temp.gcd(temp.p, temp.q);
	temp.p /= g;
	temp.q /= g;
	return temp;
}

-运算符重载:

Fraction operator-(const Fraction& F1, const Fraction& F2) {
	Fraction temp(F2);
	temp.p *= -1;			//temp取F2的负数
	return (F1 + temp);		//复用了对+的重载,减少代码量
}

下面附上main.cpp的完整代码:

#include<iostream>
#include"Fraction.h"
using namespace std;
int main() {
	srand((unsigned)time(NULL));	//随机数生成数据
	Fraction f1(rand() % 3 + 1, rand() %4  + 2);
	Fraction f2(rand() % 3 + 1, rand() %4  + 2);
	Fraction f3=f1+f2;
	Fraction f4 = f1 - f2;
	Fraction f5=  f1 * f2;
	Fraction f6 = f1 / f2;
	f1.Output();
	f2.Output();
	f3.Output();
	f4.Output();
	f5.Output();
	f6.Output();

}

//Fraction类的实现:

Fraction::Fraction(int m, int n) {
	int g = gcd(m, n);
	p = m / g;			//同时除以最大公约数
	q = n / g;
}
int Fraction::gcd(int a, int b)const
{	//辗转相除法,返回最大公约数
	int r;
	while (b) {
		r = b;
		b = a % b;
		a = r;
	}
	return (a == 0 ? 1 : a);	
}
void Fraction::Output() {
	cout << p << "/" << q<<endl;
}
Fraction& Fraction::operator++() {		//前自增
	p++;
	int g = gcd(p, q);
	p /= g;
	q /= g;
	return *this;			//返回当前对象的引用
}
Fraction Fraction::operator++(int) {	//后自增
	Fraction temp(*this);	//用默认拷贝构造函数,把当前对象保存在temp里
	p++;
	int g = gcd(p, q);
	p /= g;
	q /= g;
	return temp;
}

Fraction operator+(const Fraction& F1, const Fraction& F2) {
	Fraction temp(0, 0);
	temp.q = F1.q * F2.q;
	temp.p = F1.q * F2.p + F2.q * F1.p;
	int g = temp.gcd(temp.p, temp.q);
	temp.p /= g;
	temp.q /= g;
	return temp;
}
Fraction operator-(const Fraction& F1, const Fraction& F2) {
	Fraction temp(F2);
	temp.p *= -1;			//temp取F2的负数
	return (F1 + temp);		//复用了对+的重载,减少代码量
}
Fraction operator*(const Fraction& F1, const Fraction& F2) {
	Fraction temp(1, 1);
	temp.p = F1.p * F2.p;
	temp.q = F1.q * F2.q;
	int g = temp.gcd(temp.p, temp.q);
	temp.p /= g;
	temp.q /= g;
	return temp;
}
Fraction operator/(const Fraction& F1, const Fraction& F2) {
	Fraction temp(F2);
	int t = temp.p;
	temp.p = temp.q;
	temp.q = t;		//颠倒F2的分子分母用来
	return F1 * temp;	//复用*运算符重载,减少代码量
}

 文件结构如下:

 

尾声:

介绍一个小技巧!VS编译环境下,Ctrl+ M+O可以一键折叠所有的代码块。Ctrl+M+L可以一键打开所有的代码块。这个快捷键在代码维护的时候非常的贴心。

最后附上运算符重载表:

 其中,=、[ ]、( )、->这四个必须是非静态成员函数方式的重载。

举报

相关推荐

0 条评论