Math++ 开发(2) - 分数类的编写
知识点
class
的使用c++重载操作符
:operator
this
指针qc
的基本使用.ui
文件默认参数
的使用
今天的源码
fraction.cpp
#include "fraction.h"
Fraction::Fraction(int a, int b)
{
if (b == 0)
{
return;
}
this->a = a;
this->b = b;
}
Fraction Fraction::operator+(Fraction ot)
{
int _up, _down;
_down = this->b * ot.b;
_up = this->a * ot.b + ot.a * this-> b;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
Fraction Fraction::operator-(Fraction ot)
{
int _up, _down;
_down = this->b * ot.b;
_up = this->a * ot.b - ot.a * this-> b;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
Fraction Fraction::operator*(Fraction ot)
{
int _up, _down;
_up = this->a * ot.a;
_down = this->b * ot.b;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
Fraction Fraction::operator/(Fraction ot)
{
int _up, _down;
_up = this->a * ot.b;
_down = this->b * ot.a;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
int Fraction::measure(int x, int y)
{
int z = y;
while(x%y!=0)
{
z = x%y;
x = y;
y = z;
}
return z;
}
void Fraction::view(void)
{
qDebug() << this->a << "/" << this->b << endl;
}
void Fraction::setA(int inp)
{
this->a = inp;
}
void Fraction::setB(int inp)
{
this->b = inp;
}
fraction.h
#ifndef FRACTION_H
#define FRACTION_H
#include <QDebug>
class Fraction
{
public:
Fraction(int a=0, int b=1);
Fraction operator+(Fraction ot);
Fraction operator-(Fraction ot);
Fraction operator*(Fraction ot);
Fraction operator/(Fraction ot);
void view(void);
void setA(int inp);
void setB(int inp);
int a, b;
private:
int measure(int x, int y);
};
#endif // FRACTION_H
过程详解
创建工程
qc - 文件 - 新建(ctrl+n)
弹出新建对话框
这不有手就行
这个qmake别去改它,
解释一下:class name是程序主类,暂且就叫MainWindow
吧.Base class
:顾名思义,基类,也就是MainWindow要继承的类.Header file
:这个类的头文件Source file
:源文件
**最下面是重点:**那个复选框勾上.表示"从界面文件创建界面",也就是下面的mainwindow.ui
,下面会做解释.
ok,下一步.
这个不管他.
这个建议都勾上,运行套件,编译用的.
最后,那个版本控制系统,加不加无所谓,最好加,我就用git
,没毛病.
.ui文件解释
这玩意只能用qc解释,xml文档格式,用于储存"form",也就是所谓的"界面样式"
由于咱还是新手,不会纯代码编程,暂时用这个可视化的练练手吧…
(插个题外话,不是我瞎说,真的,用ui比纯代码快好多,特别是这种基本静态的界面)
主体编写
创建完后长这样:(因为是写完后才写的文章,所以嘛…)
右键项目名称,(在文件栏里),add new…
填一个类名:Fraction
(分数)
多了两个文件:fraction.h和fraction.cpp(分别在Headers
和Sources
里).
我们先复习一下:C++中,头文件中放声明,源文件中放实现,所以,在fraction.cpp中编写了成员函数等之后,一定要在fraction.h中声明.
首先,因为要在类外访问,所以存放分母(a),分子(b)的变量应放在public
中.
int a, b;
类构造函数:Fraction::Fraction(int a=0, int b=0);
Fraction::Fraction(int a, int b)
{
if (b == 0)
{
return;
}
this->a = a;
this->b = b;
}
这里注意:数学中,分母不为零,所以b==0时直接返回.
接下来两行:分别将传入参数放进定义好的整型变量中.
而在头文件中,我们则这样声明:
Fraction(int a=0, int b=1);
注意到了吗?我们只在头文件成员函数定义中给出了默认值,而源文件中则不用,也不能,不然会报:
重定义默认参数.
为了方便查看分数的状态,我们给出Fraction::view(void)
void Fraction::view(void)
{
qDebug() << this->a << "/" << this->b;
}
QDebug
是qt用于输出调试信息的,所以要包含头文件:
#include <QDebug>
要输出,则用插入操作符<<
传给qDebug()
再定义两个设置函数
void Fraction::setA(int inp)
{
this->a = inp;
}
void Fraction::setB(int inp)
{
this->b = inp;
}
我们来测试一下.
//main.cpp
#include "mainwindow.h"
#include "fraction.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
//w.show();
Fraction f1(12, 24);
f1.view();
Fraction f2(13, 43);
f2.view();
return a.exec();
}
ctrl+r运行,然后手动kill进程"mathplusplus.exe"得到如下:
接下来;编写操作符重载.先来个简单点的,乘和除.(乘->上乘上,下乘下, 除->上乘下作上)
Fraction Fraction::operator*(Fraction ot)
{
int _up, _down;
_up = this->a * ot.a;
_down = this->b * ot.b;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
Fraction Fraction::operator/(Fraction ot)
{
int _up, _down;
_up = this->a * ot.b;
_down = this->b * ot.a;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
大概了解原理后,可以写出+和-:
Fraction Fraction::operator+(Fraction ot)
{
int _up, _down;
_down = this->b * ot.b;
_up = this->a * ot.b + ot.a * this-> b;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
Fraction Fraction::operator-(Fraction ot)
{
int _up, _down;
_down = this->b * ot.b;
_up = this->a * ot.b - ot.a * this-> b;
int cand = this->measure(_up, _down);
return Fraction(_up / cand, _down / cand);
}
测试一下:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
//w.show();
Fraction f1(1, 4);
f1.view();
Fraction f2(1, 3);
f2.view();
(f1 * f2).view();
(f1 / f2).view();
(f1 + f2).view();
(f1 - f2).view();
//return a.exec();
return 0;
}
20:36:10: Starting D:\Program Files\Projects\build-mathplusplus-Desktop_Qt_5_9_9_MinGW_32bit-Debug\debug\mathplusplus.exe ...
1 / 4
1 / 3
1 / 12
3 / 4
7 / 12
1 / -12
20:36:10: D:\Program Files\Projects\build-mathplusplus-Desktop_Qt_5_9_9_MinGW_32bit-Debug\debug\mathplusplus.exe exited with code 0
差点忘了,还有一个重要的成员函数measure
,最小公约数,用于约分.
int Fraction::measure(int x, int y)
{
int z = y;
while(x%y!=0)
{
z = x%y;
x = y;
y = z;
}
return z;
}
总结
今天我们编写了分数 类,为什么?
数学是严谨的,容不得半点马虎.
c++提供的double,float,都有精确度的问题,而且数学中的分数大多转换成小数无限循环,多次计算,然后取近似数,久而久之,精确度就像照相机"一米之外人畜不分",这显然不是我们想要的,所以就有了这个类.
项目是久而久之累积起来的,每一个组件,模块都要精心设计,精心编写.当我们认真对待每一句代码时,学习效果,作品,总能回报付出!