我目前正在查看一个旧的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==
应该以其他方式实现?
答案 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)
语义上是(意味着==应该是!=的逻辑补充),但实际上(编码)你不必。