问题
In a question regarding the use of typeid is C++, I suggested it could be used to compare types in objects comparison. I haven't seen it done much, but I had Java's equals
in mind.
Looking into Java a bit more, this seems to be the case: Some say the actual classes of the two objects should be compared, and some say instanceof
is the right tool to use, possibly with double dispatch. There are of course cases in which one of the two is definitively more suitable, but at least both options are considered.
In C++, OTOH, I could barely find code in which the actual types are compared. On most cases, double dispatch is used (with dynamic_cast
), and I couldn't find anyone insisting a quick type comparison is the right thing to do at the beginning of the equality check.
I'm wondering why the problem of polymorphic type comparison has two acceptable solutions in Java, while in C++ only one seems to be considered the best practice? Are there significant technical differences, or just different approaches?
Note: My claims are based on impression, not concrete knowledge. If they are wrong and Java and C++ are indeed similar in that aspect - or different for reasons other than the above, it will obviously be an acceptable answer.
回答1:
In Java, all types ultimately derive from Object
, and Object
defines a virtual function Object.equals(Object other)
, so you
can compare anything with anything else, regardless of whether
it makes sense or not. In C++, there is no univeral base, and
there is no implicit definition of ==
. ==
is normally only
overridden when it makes sense, for comparing objects of the
same type, and the compiler will complain if you write nonsense
code. In cases where there is an inheritance hierarchy, it is,
of course, up to the author to decide whether ==
makes sense
(I usually doesn't, but there are a lot of exceptions), and if
so, what it should mean with respect to comparing objects of
different types. Within the hierarchy, or outside of it: it
might make sense to support ==
between BigInteger
and
BigFloat
, for example, even if the classes aren't related by
inheritance.
The reason you don't see the problem discussed much in C++ is,
of course, because you don't define ==
unless there's some
logical meaning for it, and then you define it according to the
logical meaning. In Java, you generally have to define equals
regardless, so you have to "invent" some meaning, and you get
discussion over what the invented meaning should be.
回答2:
An obvious difference is that Java equals
is a virtual method (since all Java methods are by default), so will do dynamic dispatch based on its target.
C++ operator==
overloads are statically resolved, but it's easy to delegate to a virtual function if you want polymorphic behavior.
Except for the difference in polymorphism, all other behavior is completely up to the implementer of the particular type (or in the C++ case, the implementer of a freestanding operator==
).
回答3:
Java has a single base-type for all reference types -- all reference types extend java.lang.Object
(modulo null
which breaks equals
symmetry since (null).equals(...)
is an error).
So you can say in Java "do these two java references point to equivalent things?" without knowing anything about the types of the references, so Java has a place to hang an equals(Object)
method of its base reference type, java.lang.Object
in a way that C++ does not. In C++ there is no such base-type so you have a multitude of different ==
operator and the compiler has to be able to figure out statically which to use.
Since Java objects always carry RTTI and all dispatch to an instance method is speced as virtual, there are things you can do with reflection when defining equivalence classes in code that you simply cannot with C++ objects.
回答4:
Making C++ == equivalent to Java's equals assumes that you've overridden the == operator to do "deep equals" in C++ and the Java "equals" to do the same.
来源:https://stackoverflow.com/questions/6767423/what-is-the-difference-between-javas-equals-and-cs-operator