设为首页 加入收藏

TOP

C++:声明为非成员函数的时机
2014-11-01 12:45:06 来源: 作者: 【 】 浏览:48
Tags:声明 成员 函数 时机

  我谈到让一个类支持隐式类型转换通常是一个不好的主意。当然,这条规则有一些例外,最普通的一种就是在创建数值类型时。例如,如果你设计一个用来表现有理数的类,允许从整数到有理数的隐式转换看上去并非不合理。这的确不比 C++ 的内建类型从 int 到 double 的转换更不合理(而且比 C++ 的内建类型从 double 到 int 的转换合理得多)。在这种情况下,你可以用这种方法开始你的 Rational 类:


  class Rational {


  public:


  Rational(int numerator = 0, // ctor is deliberately not explicit;


  int denominator = 1); // allows implicit int-to-Rational


  // conversions


  int numerator() const; // accessors for numerator and


  int denominator() const; // denominator - see Item 22


  private:


  ...


  };


  你知道你应该支持类似加,乘等算术运算,但是你不确定你应该通过成员函数还是非成员函数,或者,非成员的友元函数来实现它们。你的直觉告诉你,当你拿不准的时候,你应该坚持面向对象。你知道这些,于是表示,有理数的乘法与 Rational 类相关,所以在 Rational 类内部为有理数实现 operator* 似乎更加正常。与直觉不符,将函数放置在它们所关联的类的内部的主意有时候与面向对象的原则正好相反,但是让我们将它放到一边,来研究一下将 operator* 作为 Rational 的一个成员函数的主意:


  class Rational {


  public:


  ...


  const Rational operator*(const Rational& rhs) const;


  };


  (如果你不能确定为什么这个函数声明为这个样子――返回一个 const by-value 的结果,却持有一个 reference-to-const 作为它的参数。)


  这个设计让你在有理数相乘时不费吹灰之力:


  Rational oneEighth(1, 8);


  Rational oneHalf(1, 2);


  Rational result = oneHalf * oneEighth; // fine


  result = result * oneEighth; // fine


  但是你并不感到满意。你还希望支持混合模式的操作,以便让 Rationals 能够和其它类型(例如,int)相乘。毕竟,很少有事情像两个数相乘那么正常,即使它们碰巧是数字的不同类型。


  当你试图做混合模式的算术运算时,可是,你发现只有一半时间它能工作:


  result = oneHalf * 2; // fine


  result = 2 * oneHalf; // error!


  这是一个不好的征兆。乘法必须是可交换的,记得吗?


  当你重写最后两个例子为功能等价的另一种形式时,问题的来源就变得很明显了:


  result = oneHalf.operator*(2); // fine


  result = 2.operator*(oneHalf); // error!


  对象 oneHalf 是一个包含 operator* 的类的实例,所以编译器调用那个函数。然而,整数 2 与类没有关系,因而没有 operator* 成员函数。编译器同样要寻找能如下调用的非成员的 operator*s(也就是说,在 namespace 或全局范围内的 operator*s):


  result = operator*(2, oneHalf); // error!


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇如何检测C++的内存泄漏 用哪些工.. 下一篇数据结构学习(C++)之栈和队列

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: