类设计与声明之实现有理数类
占楼,学习并设计规则。
http://blog.csdn.net/qq_38238112/article/details/77416146
http://blog.csdn.net/chenkangli/article/details/489725
https://www.cnblogs.com/laizhenghong2012/p/8457784.html
http://blog.csdn.net/geophyman/article/details/16827847
分清类的成员函数、非成员函数和友元函数
- 成员函数:定义在类内部的函数,支持重载。
- 非成员函数:定义在类外部,可以被调用但不可以访问对象私有变量的函数,不支持重载。
- 友元函数:定义在类外部,可以被调用但可以访问对象私有变量的函数,不支持重载。
- 使用规则如下:只有非成员函数对最左边的参数进行类型转换。如果需要对最左边的参数进行类型转换例如
2 * oneHalf;
,让其成为非成员函数。如果还需要访问对象的非公有成员,让其成为类的友元函数。其它情况下都声明为成员函数。如果以上情况都不是,让其成为类的成员函数。
const Rational operator*(const Rational& rhs) const;//定义为成员函数
result = oneHalf * 2; //正确,相当于调用对象的成员函数oneHalf.operator*(2),条件满足下2隐式转换为Rational。
result = 2 * oneHalf; //错误,2不是对象,所以不能调用对象的成员函数,编译报错。
//如果const Rational operator*(const Rational& rhs) const;是非成员函数
//那么编译器会根据重载情况,调用对应的非成员函数,并且如果需要访问类的私有变量,此函数必须声明为友元函数。
设计Rational类
1、算术运算,包括加减乘除
必须支持Rational对象之间的算术运算,也支持Rational对象和数字之间的算术运算,也就是下面的类必须很好的支持。
Rational oneEighth(1, 8);
Rational Rational oneHalf(1, 2);
Rational result;
result = oneEighth + oneHalf;//支持
result = 2 + result;//支持
result = result + 2;//支持
根据上面函数类别的分析。必须将算术运算函数重载为友元非成员函数才可以。友元是因为需要访问对象私有变量,外部函数可以保证编译自动调用,并强制转换对应的参数。
2、支持cout和cin
如果operator>>和operator<<
重载为成员函数,那么调用将是result >> cin和result << cout
,看着很别扭,所以必须定义为外部函数,让编译器根据符号左右两边参数选择对应的函数执行。
3、求解最大公约数
利用辗转相除法也叫欧几里得算法,是一种非常古老的求解两个数的最大公约数的算法。其基于的原理:两个正整数a和b(a > b),它们的最大公约数gcd等于a除以b的余数r和b之间的最大公约数。比如,10和25的最大公约数5等于25除以10的余数5和10的最大公约数;再比如51和21的最大公约数3等于51除以21的余数9和21的最大公约数,而9和21的最大公约数为3。辗转相除法的算法流程可以如下:
步骤1:计算a与b的余数r。
步骤2:如果r为0,则返回gcd = b。否则,转到步骤3。
步骤3:使用b的值更新a的值,使用余数r更新b的值,转到步骤1。
3、实现类
推荐阅读