Interfaces or pure virtual classes are not the same because they're closed.
The advantage that Haskell's typeclasses have over either Java or C++ is that the types aren't closed. I can define a new typeclass and tell the compiler that a type you defined is a member of that class at any point. In Java, if you don't define that your type is Comparable, there's nothing that I, as a consumer of your type, can do about it.
(A) Ability to instantiate old types with new classes
(B) Conditional instantiation: "Maybe a" is an instance of "Show" iff "a" is an instance of "Show"
(C) Can do return-type polymorphism, or polymorphism on any part of the signature
(D) Objects do not need to pay for the interface vtable pointer. Large array of some type-class instance can be much smaller than an array of an OOP interface subclass.
(E) When comparing two Ord instance values, there is only one Ord dictionary, rather than 2 to choose from. No false dilemma.
One type -> at most one instance for any class, in Haskell.
The error you get if you try to sort a vector with an unordered type is relatively easy to read:
main.cpp: In instantiation of 'void merge_sort(std::vector<_RealType>&) [with T = type]':
main.cpp:45:17: required from here
main.cpp:30:5: error: static assertion failed: Element type is not sortable
static_assert( concept::is_ord<T>(), "Element type is not sortable" );
^