• 条款24:若所有的函数参数可能都需要发生类型转换才能使用,请采用non-member函数


    假设有一个有理数类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函数。

  • 相关阅读:
    listview 加载性能优化 viewholder
    eclipse使用有感
    android常见的错误
    填充父窗体布局问题
    setTag()/getTag()
    自己动手实现自旋锁
    新手学信息检索6:谈谈二值独立模型
    自己动手编译、运行Java程序
    新手学信息检索5:正确率召回率与搜索引擎的评价
    新手学信息检索4:向量空间模型与相似度计算
  • 原文地址:https://www.cnblogs.com/benxintuzi/p/4539873.html
Copyright © 2020-2023  润新知