benxintuzi

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

假设有一个有理数类Rational,有一个计算有理数乘法的成员函数operator*,示例如下:

 1 #include <iostream>
 2 
 3 class Rational
 4 {
 5 public:
 6     Rational(int numerator = 0, int denominator = 1)
 7     {
 8         n = numerator;              // 分子
 9         d = denominator;            // 分母
10     }
11     int numerator() const
12     {
13         return n;
14     }
15     int denominator() const
16     {
17         return d;
18     }
19     const Rational operator*(const Rational& rhs) const
20     {
21         return Rational(this->n * rhs.n, this->d * rhs.d);
22     }
23 
24 private:
25     int n;
26     int d;
27 };
28 
29 int main()
30 {
31     Rational oneEight(1, 8);
32     Rational oneHalf(1, 2);
33     Rational result1 = oneEight * oneHalf;  // 同类型运算
34     Rational result2 = oneHalf * 3;         // 混合运算1
35     Rational result3 = 3 * oneHalf;         // 混合运算2  
36 
37     std::cout << result1.numerator() << "/" << result1.denominator() << std::endl;
38     std::cout << result2.numerator() << "/" << result2.denominator() << std::endl;
39     std::cout << result3.numerator() << "/" << result3.denominator() << std::endl;
40 
41     return 0;
42 }

如上可见,该乘法运算对于执行同类型运算没有任何问题,为什么对于执行混合运算却有时可以,有时又不可以呢?其实,我们知道执行oneHalf * 3时,编译器调用oneHalf的成员函数,然后对于3执行隐式类型转换(调用Rational的构造函数完成的),转换为Rational后执行乘法运算,因此没出现错误;但是对于3 * oneHalf而言就不同了,因为3并没有相应的成员函数,因此,编译器将试图寻找non-member operator*:result = operator*(2, oneHalf),但是很遗憾,你没有提供这样的函数,因此发出错误。因此结论是:像这种需要发生类型转换才能继续工作的函数,你必须提供一个non-member函数来完成工作,示例如下:

1 const Rational operator*(const Rational& lhs, const Rational& rhs)
2 {
3     return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
4 }

 

这样的话上述的两种混合调用方式都可以通过了。因此请记住如下结论:

当你设计的某个函数的所有参数(包含this指针所指的那个隐含参数)都可能需要发生类型转换时,那么这个函数必须是non-member函数。

 

posted on 2015-05-30 09:59  benxintuzi  阅读(403)  评论(0编辑  收藏  举报