| > there's little coherence to the way the language has grown in the last decade. IMHO it's been incoherent from the earliest times. The lame exceptions without 'finally', and no consistency in exception types. Then the desperate attempts to make all resources into objects, except that practically no OS calls bothered with this. The overloading of the shift operators in the standard library. Indeed, operator overloading itself is just a recipe for abuse. You read 'a=b+c' and you literally have no clue what that means. Multiple inheritance with the brittle semantics. The awful STL, with its multi-kB error messages (the allocator of the trait of the string of the tree of map of king Caractacus doesn't match ...) There's no wonder the 'obfuscated C competition' never happened with C++ given the fact it's unreadable, right out of the box. |
I never understood that argument. Even in C operators do different things depending on what types you pass it. Two very simple examples:
1. Adding a number to a char* vs adding a number to an int* (or a pointer to any other larger type). The second automatically creates an invisible multiplication. This was confusing for me when I first learned C after already knowing the concept of a memory address (which is just a number). It was an unexpected abstraction for me.
2. This regularly bites novices to programming: Dividing two numbers. If at least one of them is floating point, you get the 'correct' result, overwise rounded towards zero. To 'fix' it, you have to explicitly cast at least one of them to float or double. Then the language imlpicitly casts the other for you. std::pow went the other way, which is less confusing. It always promotes integers to floating point numbers and returns a floating point result.
As soon as your language has types and operators, you get operators that do different things based on the types of the values they are applied to. The only new thing that operator overloading adds is that it makes libraries first class citizens.