10

关于使用typeidis C++ 的问题中,我建议它可以用于比较对象比较中的类型。我还没有看到它做了太多,但我想到了 Java equals

再深入研究一下 Java,似乎是这样:有人说应该比较两个对象的实际类,有人说 instanceof是使用正确的工具,可能是双重分派。当然,在某些情况下,两者中的一个肯定更合适,但至少两个选项都被考虑在内

在 C++ OTOH 中,我几乎找不到用于比较实际类型的代码。在大多数情况下,使用双重分派(with dynamic_cast),我找不到任何人坚持快速类型比较是在平等检查开始时做的正确事情。

我想知道为什么多态类型比较的问题在 Java 中有两种可以接受的解决方案,而在 C++ 中似乎只有一种被认为是最佳实践?是否存在显着的技术差异,或者只是不同的方法?

注意:我的说法是基于印象,而不是具体知识。如果它们是错误的,并且 Java 和 C++ 在这方面确实相似——或者由于上述以外的原因而不同,那么这显然是一个可以接受的答案。

4

4 回答 4

7

在 Java 中,所有类型最终都派生自ObjectObject 定义了一个虚函数Object.equals(Object other),因此您可以将任何东西与其他任何东西进行比较,无论它是否有意义。在 C++ 中,没有通用基础,也没有隐式定义==. ==通常仅在有意义时才被覆盖,用于比较相同类型的对象,如果您编写无意义的代码,编译器会抱怨。在存在继承层次结构的情况下,当然由作者来决定是否==有意义(我通常没有,但有很多例外),如果是的话,它应该意味着什么比较不同类型的对象。在层次结构内部或外部:在和 ==之间支持可能是有意义的BigIntegerBigFloat,例如,即使类不通过继承相关。

你看不到 C++ 中讨论的问题的原因当然是因为你不定义==,除非它有一些逻辑意义,然后你根据逻辑意义来定义它。在 Java 中,您通常必须定义equals 无论如何,因此您必须“发明”一些含义,并且您会讨论所发明的含义应该是什么。

于 2011-07-20T20:28:03.173 回答
2

一个明显的区别是Javaequals是一个虚拟方法(因为所有Java方法都是默认的),所以会根据它的目标进行动态调度。

C++operator==重载是静态解决的,但如果您想要多态行为,很容易委托给虚函数。

除了多态性的差异之外,所有其他行为完全取决于特定类型的实现者(或者在 C++ 情况下,独立的实现者operator==)。

于 2011-07-20T19:37:42.013 回答
1

Java 对所有引用类型都有一个基本类型——所有引用类型都扩展java.lang.Object(模数null会破坏equals对称性,因为这(null).equals(...)是一个错误)。

所以你可以在 Java 中说“这两个 Java 引用是否指向等价的东西?” 在不知道引用类型的情况下,Java 有一个地方可以挂起equals(Object)它的基本引用类型java.lang.Object的方法,而 C++ 没有。在 C++ 中没有这样的基本类型,因此您有大量不同的==运算符,编译器必须能够静态地找出要使用的运算符。

由于 Java 对象总是携带 RTTI 并且所有对实例方法的分派都被指定为虚拟的,因此在代码中定义等价类时,您可以使用反射来做一些使用 C++ 对象无法做到的事情。

于 2011-07-20T19:39:33.213 回答
0

使 C++ == 等效于 Java 的 equals 假设您已经覆盖了 == 运算符以在 C++ 中执行“深度等于”并且 Java“等于”执行相同的操作。

于 2011-07-20T19:36:35.587 回答