I'm learning about operator overloading in C++, and I see that == and != are simply some special functions which can be customized for user-defined types. My concern is, though, why are there two separate definitions needed? I thought that if a == b is true, then a != b is automatically false, and vice versa, and there is no other possibility, because, by definition, a != b is !(a == b). And I couldn't imagine any situation in which this wasn't true. But perhaps my imagination is limited or I am ignorant of something?

我知道我可以用一个定义另一个,但这不是我要问的。我也没有问通过值和单位来比较对象之间的区别。或者两个对象是否可以同时相等和不相等(这绝对不是一个选项!这些事情是相互排斥的)。我想问的是:

有没有可能在这种情况下,问两个对象是否相等的问题是有意义的,但问它们不相等的问题是没有意义的?(无论是从用户的角度,还是从实现者的角度)

如果没有这种可能性,那么究竟为什么c++将这两个操作符定义为两个不同的函数呢?


当前回答

(. .为什么需要两个不同的定义?

需要考虑的一件事是,实现其中一个操作符可能比仅使用另一个操作符的反求值更有效。

(我这里的例子是垃圾,但重点仍然成立,想想bloom过滤器,例如:它们允许快速测试,如果某些东西不在集合中,但测试它是否在集合中可能需要更多时间。)

(. .根据定义,a != b是!(a == b)。

这是你作为程序员的责任。这可能是编写测试的好方法。

其他回答

也许是一个不可比较的规则,其中a != b为假,a == b为假,就像一个无状态位。

if( !(a == b || a != b) ){
    // Stateless
}

有没有可能的情况是问关于二的问题 对象相等是有意义的,但是问它们不相等 相等没有意义吗?(无论是从用户的角度,还是从 实现者的角度)

这只是个人观点。也许不是。但是语言的设计者并不是无所不知的,他们决定不限制那些可能想出有意义的情况的人(至少对他们来说)。

enum BoolPlus {
    kFalse = 0,
    kTrue = 1,
    kFileNotFound = -1
}

BoolPlus operator==(File& other);
BoolPlus operator!=(File& other);

我不能证明这个操作符重载是正确的,但在上面的例子中,不可能定义操作符!作为运算符==的“对立面”。

如果==和!=操作符实际上并不意味着相等,就像<<和>>流操作符并不意味着位移位一样。如果你把这些符号当作其他概念来对待,它们就不必相互排斥。

就相等而言,如果您的用例保证将对象视为不可比较的,那么每次比较都应该返回false(或者如果操作符返回非bool类型,则返回不可比较的结果类型),那么这样做是有意义的。我想不出一个具体的情况,这将是必要的,但我可以看到它是足够合理的。

如果没有这种可能性,那么究竟为什么c++将这两个操作符定义为两个不同的函数呢?

因为你可以让它们超载,通过超载,你可以赋予它们一个与原来完全不同的含义。

例如,操作符<<,最初是位左移操作符,现在通常重载为插入操作符,如std::cout << something;和原来的意思完全不同。

因此,如果您接受重载操作符时操作符的含义会发生变化,那么就没有理由阻止user给operator ==赋予一个与operator !=不完全相反的含义,尽管这可能会令人困惑。