C 箴言:声明为非成员函数时机

2008-02-23 05:40:46来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

  我谈到让一个类支持隐式类型转换通常是个不好的主意。当然,这条规则有一些例外,最普通的一种就是在创建数值类型时。例如,假如您设计一个用来表现有理数的类,允许从整数到有理数的隐式转换看上去并非不合理。这的确不比 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!

  但是在本例中,没有非成员的持有一个 int 和一个 Rational 的 operator*,所以搜索失败。

[1] [2] 下一页




标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C 箴言:视类设计为类型设计

下一篇: C 箴言:绝不在构造或析构期调用虚函数

热门词条
热门标签