假设有一个有理数类Rational,有一个计算有理数乘法的成员函数operator*,示例如下:
#include <iostream> class Rational
{
public:
Rational(int numerator = , int denominator = )
{
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);
} private:
int n;
int d;
}; int main()
{
Rational oneEight(, );
Rational oneHalf(, );
Rational result1 = oneEight * oneHalf; // 同类型运算
34 Rational result2 = oneHalf * 3; // 混合运算1
35 Rational result3 = 3 * oneHalf; // 混合运算2 std::cout << result1.numerator() << "/" << result1.denominator() << std::endl;
std::cout << result2.numerator() << "/" << result2.denominator() << std::endl;
std::cout << result3.numerator() << "/" << result3.denominator() << std::endl; return ;
}
如上可见,该乘法运算对于执行同类型运算没有任何问题,为什么对于执行混合运算却有时可以,有时又不可以呢?其实,我们知道执行oneHalf * 3时,编译器调用oneHalf的成员函数,然后对于3执行隐式类型转换(调用Rational的构造函数完成的),转换为Rational后执行乘法运算,因此没出现错误;但是对于3 * oneHalf而言就不同了,因为3并没有相应的成员函数,因此,编译器将试图寻找non-member operator*:result = operator*(2, oneHalf),但是很遗憾,你没有提供这样的函数,因此发出错误。因此结论是:像这种需要发生类型转换才能继续工作的函数,你必须提供一个non-member函数来完成工作,示例如下:
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
}
这样的话上述的两种混合调用方式都可以通过了。因此请记住如下结论:
当你设计的某个函数的所有参数(包含this指针所指的那个隐含参数)都可能需要发生类型转换时,那么这个函数必须是non-member函数。