设计一个表示有理数的类时,允许从整数隐式转换为有理数是有用的:
class Rational {
public:
Rational(int numerator = 0, // 该构造函数没有explicit限制;
int denominator = 1);
int numerator() const;
int denominator() const;
const Rational operator*(const Rational& rhs) const;
private:
int n,d;
};
Rational oneEighth(1, 8);
Rational oneHalf(1, 2);
Rational result = oneHalf * oneEighth; // 正确
result = result * oneEighth; // 正确
result = oneHalf * 2; // result = oneHalf.operator*(2); 正确
result = 2 * oneHalf; // result = 2.operator*(oneHalf); 错误!
乘法应该是可交换的,但是由于参数的隐式类型转换只发生在参数列表中,所以2 * oneHalf会报错,由于2是int类型的参数。
这时候我们可以将operator重载函数修改为非成员函数,编译器还会寻找非成员运算符(即命名空间或全局作用域中的运算符):
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
Rational oneFourth(1, 4);
Rational result;
result = oneFourth * 2; // 正确
result = 2 * oneFourth; // 欧耶,它起作用了!
#include <iostream>
class Rational {
public:
Rational(int numerator = 0, // 该构造函数没有explicit限制;
int denominator = 1):n{numerator},d{denominator}
{ }
int numerator() const {
return n;
}
int denominator() const {
return d;
}
//const Rational operator*(const Rational& rhs) const {
// return Rational(this->n*rhs.n,this->d*rhs.d);
//}
void print() const {
if(n%d==0)
std::cout << n /d << std::endl;
else if(d%n==0)
std::cout << 1 << "/" << d/n << std::endl;
else
std::cout << n << "/" << d << std::endl;
}
private:
int n, d;
};
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
int main()
{
Rational oneEighth(1, 8);
Rational oneHalf(1, 2);
Rational result = oneHalf * oneEighth; // 正确
result = result * oneEighth; // 正确
result.print();
result = oneHalf * 2; // result = oneHalf.operator*(2); 正确
result.print();
result = 2 * oneHalf; // result = 2.operator*(oneHalf);
result.print();
}