Java的equals()和C++的operator==有什么区别?

10
在C++中,有关使用typeid的问题,我建议可以用它来比较对象类型。虽然我没有看到过这样的做法,但我想到了Java的equals进一步研究Java后,似乎的确如此:有人说应该比较两个对象的实际类,有人说instanceof是正确的工具,可能需要双重分派。当然,在某些情况下,其中一个显然更适合,但至少两种选择都被考虑
在C++中,实际上很难找到比较实际类型的代码。在大多数情况下,使用双重分派(使用dynamic_cast),我找不到任何人坚持在相等性检查开始时进行快速类型比较是正确的事情。
我想知道为什么在Java中多态类型比较的问题有两个可接受的解决方案,而在C++中只有一个被认为是最佳实践?是否存在重大技术差异,还是只是不同的方法?

注意:我的观点基于印象,而非具体知识。如果它们是错误的,并且Java和C++在这方面确实相似 - 或者出于其他原因不同,那么这显然是可以接受的答案。


在C++中,==可以被重载 - 因此它取决于上下文... - Seb Holzapfel
2
@Schnommus:在Java中,equals方法可以被覆盖重写。差别不大。 - Ben Voigt
1
@Ben Voigt:说得好。如果不是为了读者,我会删除我的评论。 - Seb Holzapfel
1
在C++中,类不会自动带有operator==方法。如果一个类需要这个功能,它必须重载operator==方法。 - Thomas Matthews
4个回答

7
在Java中,所有类型最终都是从Object派生而来的,而Object定义了一个虚函数Object.equals(Object other),因此您可以比较任何东西,无论它是否有意义。 在C ++中,没有通用基础,并且没有隐式定义的== 。只有在比较相同类型的对象时才被覆盖,编译器会在编写无意义代码时发出警告。在存在继承层次结构的情况下,当然由作者决定是否应该使用 == (我通常不这样做,但有很多例外),如果使用,应该意味着什么以便比较不同类型的对象。在层次结构内部或外部:例如,在BigInteger和BigFloat之间支持==可能是有意义的,即使这些类没有通过继承相关联。
当然,在C++中你不会经常看到这个问题讨论,因为除非有某种逻辑上的含义,否则你不会定义== ,然后根据逻辑含义定义它。在Java中,您通常必须定义equals,因此您必须“发明”一些含义,并且您将讨论发明的含义应该是什么。

2
一个明显的区别在于Java的equals是一个虚方法(因为所有Java方法默认都是这样),因此它将根据其目标进行动态分派。
C++的operator==重载是静态解析的,但是如果您想要多态行为,则很容易委托给虚函数。
除了多态性的差异外,所有其他行为完全取决于特定类型的实现者(或在C++情况下,自由operator==的实现者)。

1

Java对于所有引用类型都有单一的基础类型--所有引用类型都扩展了java.lang.Object(除了null,它会破坏equals的对称性,因为(null).equals(...)是错误的)。

因此,你可以在Java中说"这两个Java引用是否指向等效的东西?",而不需要知道引用类型的任何信息,因此Java有一个地方来挂载它的基本引用类型java.lang.Objectequals(Object)方法,而C++没有。在C ++中没有这样的基础类型,因此你有多种不同的==运算符,编译器必须静态地确定使用哪一个。

由于Java对象始终具有RTTI并且所有的派发实例方法都被规定为虚拟的,所以你可以通过反射在定义代码中的等价类时进行某些操作,而这在C++对象中是不可能做到的。


1
Java == 似乎不是这个问题的主题。 - Ben Voigt

0
假定您在C++中重写了"=="运算符以执行“深度相等”,并且在Java中使用了相同的方法,那么使C++ == 等价于Java的equals是可行的。

就像我说的那样,你必须重写equals方法来实现深度比较。请参考Joshua Bloch的《Effective Java》第3章。 - duffymo
好的。删除我的原始评论。 - Mike Samuel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接