是==和!=相互依赖吗?
我学习了C ++中的运算符重载,并且我发现==
和!=
只是一些可以为用户定义的类型定制的特殊函数。 不过,我担心为什么需要两个单独的定义? 我认为如果a == b
是真的,那么a != b
自动为false,反之亦然,并且没有其他可能性,因为根据定义, a != b
是!(a == b)
。 而我无法想象任何情况都不是这样。 但是也许我的想象力有限,或者我对某些东西一无所知?
我知道我可以用另一个来定义一个,但这不是我所问的。 我也没有问及按价值或身份比较对象的区别。 或者两个对象是否可以同时相等和不相等(这绝对不是一种选择!这些东西是相互排斥的)。 我问的是这样的:
有没有什么情况可以提出有关两个物体相同的问题是有道理的,但询问它们不相同是没有意义的? (无论是从用户角度还是从实施者的角度来看)
如果没有这种可能性,那么为什么C ++将这两个运算符定义为两个不同的函数呢?
当a == b
返回除bool
以外的内容时,您不希望语言自动将a != b
重写为!(a == b)
。 有几个原因可以让你做到这一点。
您可能有表达式构建器对象,其中a == b
不是并且不打算执行任何比较,而只是构建表示a == b
表达式节点。
您可能会有懒惰的评估,其中a == b
不会直接执行任何比较,而是会返回某种lazy<bool>
,可以稍后隐式或显式地将其转换为bool
,以便实际上执行比较。 可能与表达式构建器对象结合,以便在评估之前进行完整的表达式优化。
你可能有一些自定义的optional<T>
模板类,其中给定可选变量t
和u
,你想允许t == u
,但是使它返回optional<bool>
。
我可能还没有想到更多。 即使在这些例子中, a == b
和a != b
这两个操作都有意义,但仍然a != b
与!(a == b)
,所以需要单独的定义。
如果没有这种可能性,那么为什么C ++将这两个运算符定义为两个不同的函数呢?
因为你可以超载它们,并且通过重载它们,你可以给它们与原来的完全不同的含义。
例如,运算符<<
最初是按位左移运算符,现在通常作为插入运算符重载,就像std::cout << something
; 完全不同于原来的意思。
因此,如果您承认运算符的含义在您超载时发生了变化,那么没有理由阻止用户向运算符==
赋予含义,这不完全是运算符!=
的否定,尽管这可能会造成混淆。
不过,我担心为什么需要两个单独的定义?
你不必定义两者。
如果它们相互排斥,只需定义==
和<
沿着std :: rel_ops即可
Fom cppreference:
#include <iostream>
#include <utility>
struct Foo {
int n;
};
bool operator==(const Foo& lhs, const Foo& rhs)
{
return lhs.n == rhs.n;
}
bool operator<(const Foo& lhs, const Foo& rhs)
{
return lhs.n < rhs.n;
}
int main()
{
Foo f1 = {1};
Foo f2 = {2};
using namespace std::rel_ops;
//all work as you would expect
std::cout << "not equal: : " << (f1 != f2) << 'n';
std::cout << "greater: : " << (f1 > f2) << 'n';
std::cout << "less equal: : " << (f1 <= f2) << 'n';
std::cout << "greater equal: : " << (f1 >= f2) << 'n';
}
有没有什么情况可以提出有关两个物体相同的问题是有道理的,但询问它们不相同是没有意义的?
我们经常将这些运营商联系在一起。
尽管这是他们在基本类型上的表现,但没有义务这是他们在自定义数据类型上的行为。 如果你不想要,你甚至不需要返回一个布尔值。
我见过人们以奇怪的方式重载操作符,只是发现它对于其特定于领域的应用程序是有意义的。 即使界面看起来表明它们是相互排斥的,作者也许想要添加特定的内部逻辑。
(无论是从用户角度还是从实施者的角度来看)
我知道你想要一个具体的例子,
所以这里是我认为很实用的Catch测试框架:
template<typename RhsT>
ResultBuilder& operator == ( RhsT const& rhs ) {
return captureExpression<Internal::IsEqualTo>( rhs );
}
template<typename RhsT>
ResultBuilder& operator != ( RhsT const& rhs ) {
return captureExpression<Internal::IsNotEqualTo>( rhs );
}
这些操作符做了不同的事情,将一种方法定义为另一种方法是没有意义的。 这样做的原因是,框架可以打印出比较结果。 为了做到这一点,它需要捕捉使用重载操作符的上下文。
链接地址: http://www.djcxy.com/p/27507.html