C++ is a hack
Misguided right off the bat:<p>&gt; <i>Not only does C++ have no notion of interfaces, it actually allows subclasses to hide public methods from the superclass.</i><p>C++ doesn&#x27;t have &quot;methods&quot;; it has member functions (static or nonstatic). Nonstatic ones can be virtual. Virtual member functions are what corresponds to OOP methods.<p>To use virtual functions as methods, you call them through a base class pointer or reference to an object. That&#x27;s when you&#x27;re doing OOP dispatch.<p>Now a derived class in C++ can define member functions of the same names as a base. These functions lexically shadow the ones in the base. If you use derived objects as their actual derived type (not through a base reference), then you&#x27;re using those functions. This is &quot;statically clear&quot; in a static language, and it makes sense. If I open up &quot;program.cpp&quot; in my text editor and edit some function so that a &quot;Foo f&quot; object is replaced by a &quot;DerivedFoo f&quot;, then I want all occurrences of f.func() to now be calling DerivedFoo::f rather than Foo::f, if DerivedFoo::f exists.  I don&#x27;t want the compiler to complain that the situation is ambiguous, and I don&#x27;t want it to keep calling Foo::f, which is nonsensical.<p>Lastly, access is orthogonal to visibility in C++; it is not accurate to say things like &quot;allows subclasses to hide public methods&quot;.  Identifiers declared in the derived class scope simply shadow like-named definitions in base classes, period. That is regardless of access. Access specifiers do not alter visibility (or any program semantics). If you manipulate the access specifiers in a C++ program, at best you can make some diagnostic go away, or introduce the need for one. All permutations of access specifiers which don&#x27;t require a diagnostic will behave the same way (and should produce identical code, really).<p>&gt; <i>One of the increment operators takes a dummy int parameter in order to allow overloading. Can you tell which without googling?</i><p>Yes, I can tell without googling as can any reasonably competent C++ programmer. Why would you need to answer the question in this form? The feature is there for when the situation arises that you&#x27;re writing an overloaded ++ operator and would like it to be postfix. If you don&#x27;t care about overloading ++ or making it postfix, you don&#x27;t have to be aware that there is an int hack for this.<p>&gt; <i>Without adding another layer of indirection via the PIMPL idiom, changes to the internal structure of the class propagate to all it&#x27;s users, making compilation painfully &#x2F; unecessary slow. </i><p>The class declaration being fully visible to all places which use it allows C++ to be efficient in its handling of data types. For instance, when you have a local variable &quot;FooClass x&quot;, the compiler knows exactly how large x is down to the byte and can give it a fixed-size place in a fixed-size stack frame. It also allows for inline functions which compile to code that accesses the object directly.<p>This low-level nature is a conscious design trade off in C++, which makes it what it is. If you want to eliminate the dependencies, you use that PIMPL idiom explicitly. In some higher level languages, the equivalent of PIMPL is implicit everywhere. (For instance, everything is a &quot;heap object&quot;). C++ is one language you can reach for in situations when you don&#x27;t want everything to be a heap object, yet still have some halfway useful abstractions.<p>&gt; <i>C++ did not have any standard multithreading implementation until C++ 11.</i><p>That was five years ago. C++ users did threading in C++ code for at least twenty years before that, in platform-specific ways, or using cross platform frameworks like ACE. Because C++ doesn&#x27;t hide a lot of behaviors under the hood, you can let platform threads loose directly into C++ code and the effects are predictable and manageable, for the most part, modulo issues like &quot;does unwinding happen if the thread dies&quot; and such.<p>&gt; <i>The C++ compilator was originally a preprocessor for C (CFront), and still maintains binary compatibility with C.</i><p>This point is also inaccurate. C++ has to live in a world with <i>linkers</i> and <i>object file formats</i> which do not support type information on a symbol. That is why name mangling is required.<p>If you want three flavors of a function called foo, with separate external linkage (rather than, say, some internal runt-time dispatch behind a single function) then you need three separate entries in the symbol table.<p>In most object file formats, that means you need three different symbol names.<p>It has nothing to do with C++ originally having been preprocessed, or compatibility with C. C itself is simply compatible with assembly language linkage models. (And so C has failed to promote any improvements in object file formats and linkers, by imposing no special requirements.)<p>Some other languages have to do name mangling in their implementations, to some extent. I used a Modula-2 compiler in the late 1980&#x27;s which used a &quot;module$ident&quot; scheme in the object file format. That is to say, function foo in module bar was turned into the symbol &quot;bar$foo&quot; with a dollar sign.