应该通过C ++中的“operator ==”实现“operator!=”吗?

时间:2011-01-12 10:07:41

标签: c++ comparison operators operator-overloading

我目前正在查看一个旧的C ++代码库,并看到很多代码如下:

bool SomeClass::operator==( const SomeClass& other ) const
{
   return member1 == other.member1 && member2 == other.member2;
}

bool SomeClass::operator!=( const SomeClass& other ) const
{
   return member1 != other.member1 || member2 != other.member2;
}

显然比较逻辑是重复的,上面的代码可能必须在两个地方而不是一个地方进行更改。

AFAIK实施operator!=的典型方法是这样的:

bool SomeClass::operator!=( const SomeClass& other ) const
{
    return !( *this == other );
}

在后一种情况下,operator==中发生的任何逻辑更改都会自动反映在operator!=中,因为它只调用operator==并执行否定。

除了在C ++代码中重用operator!=之外,是否有任何合理的案例operator==应该以其他方式实现?

4 个答案:

答案 0 :(得分:9)

在大多数情况下,a!=b的语义应等于!(a==b)

对于所有其他运营商也是如此:a<b应该等于!(a=>b)!(a==b || a>b)以及a<=b && !(a==b)等等。< / p>

为此目的boost.operators提供了一些很棒的工具来自动生成其他操作符。


然而,当你给你的运算符一些特定的语义时(即:你不使用==来检查两个项是否相同,而是做一些像STL那样花哨的东西>><<)你可能想给他们不同的实现。

一般来说,这种做法并未被提出,尽管STL和许多boost库也可以这样做。


编辑 - 一点点补充:

到目前为止我所说的只关注运营商的语义。如果您认为a!=b的语义应该是!(a==b),那么您有两种方法可以实现它:

  • 通过调用另一个运算符,如果你使用boost.operators会发生这种情况:
    bool operator!=(a,b) { return !(a==b); }

  • 从头开始实施这两项工作。

第一种方法通常更容易实现,更安全。最常见的事情可以证明第二个选项是优化,虽然它可能不值得:现代编译器在大多数情况下不会增加任何开销(如果你看看boost.operators源代码,你会看到很多关于它们的评论如果编译器不提供NRVO,则依赖NRVO不增加开销,或者代码如何更改。

无论你选择哪种选项,无论如何,它应该对你的应用程序逻辑没有任何影响,因为重要的是语义(即:你的运算符如何表现,它们为任何可能的输入返回的内容)。

答案 1 :(得分:4)

恕我直言,它的实施既合理又强大!= = =。 (或者相反)

答案 2 :(得分:3)

  

除了在C ++代码中重用operator!=之外,是否有任何合理的案例operator==应该以其他方式实现?

我不这么认为。但同样适用于其他代码,例如postfix ++始终以前缀++实现(当然除了本机类型,优化器可以生成更高效的代码,但我相信即使这样,论证仍然存在并且operator +应该几乎总是operator +=的形式实现(例外情况是当您使用代理对象来延迟执行时)。

这就是std::relops存在的原因。

答案 3 :(得分:2)

语义上是(意味着==应该是!=的逻辑补充),但实际上(编码)你不必。