实现一个有理数类:
class Rational {
//friend const Rational operator* (const Rational& lhs, const Rational&rhs);
//friend bool operator== (const Rational& lhs, const Rational&rhs);
public:
Rational(int numerator = 0, int denominator = 1) : n(numerator), d(denominator) {}
int numerator() const {return n;}
int denominator() const {return d;}
private:
int n;
int d;
};
const Rational operator* (const Rational& lhs, const Rational&rhs)
{
return Rational(lhs.numerator()*rhs.numerator(), lhs.denominator()*rhs.denominator());
}
bool operator== (const Rational& lhs, const Rational&rhs)
{
if(lhs.numerator() / lhs.denominator() == rhs.numerator() / rhs.denominator()) return true;
return false;
}
int main(int argc, char *args[])
{
Rational a(10,1), b(100,1), c(1000,1), d(10000,1);
if (a*b == c*d)
cout << "yes" << endl;
else
cout << "no" << endl;
system("pause");
return 0;
}
有理数类的operator*函数需返回新对象Rational, 所以不要妄想返回reference, 因为局部对象会在函数结束之后销毁.
有理数类的operator*函数可以声明为member函数,也就是只接受一个参数,乘号*左边为调用对象本身。这种方式不能支持如下的调用:
Rational oneHalf(1,2);
Rational result = 2 * oneHalf;
因为如上调用实则发生了:
result = 2.operator*(oneHalf);
整数2没有对应的class, 也就没有operator*成员. 编译器报错.
而对于如下的调用可以编译通过:
result = oneHalf * 2;
因为编译器对2进行了隐式类型转化,生成了一个临时Rational对象. 所以, 如果Rational的构造函数是explicit的,那么以上调用依然无法编译通过。
所以如果需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.
另外,member函数的反面是non-member,而不是friend. 无论何时都应该避免friend函数。