This morning, I was reminded of (and repeated) a quip I made long ago:
C programmers are scared of the code they can't see;
C++ programmers are scared of the code they can
The C vs C++ debate is, of course, ancient and heated, so it's perhaps surprising that this quote is something that both sides agree on - and perhaps even more so that both see it as a criticism of the other. Which is to say, there's a kernel of truth here. It's pointing out the underlying philosophies of both languages (and the cultures around them)
C is a decidedly explicit language: It does very little for you, and is often touted (inaccurately) as being a "portable assembler". All dispatch is static, there is no function or operator overloading, and therefore it is very easy to predict what the behavior of a given line of code will be - well, as long as you can remember C's occasionally surprising type promotion rules.
One side of this, of course, is that C can't stop you from not doing something. It is terrifyingly easy to forget to free something and leak memory, or to forget to increment a reference count on an object you're taking a reference to, or any of a manner of things which cause your program to leak memory or explode in some location completely unrelated to the underlying bug.
C++ instead provides liberal sprinkles of magic. Function overloading. Operator overloading. Virtual dispatch. Automatic invocation of destructors at scope exit. A C programmer looks at these and is terrified by the subtle, implicit behavior, and C++'s case here isn't helped because it's just not that good a magician and occasionally blows up your desk.
(To be fair to C++, most of these dangers come from the faustian bargain it made to get where it is now, of being a mostly supserset of C)
A C++ programmer, meanwhile, comes at things from a different perspective: code written by humans is buggy;  instead, as much as possible of the complexity should be shuffled to the compiler. Abstractions should be built so that the intent of the code is clear.
They build a complex math library as a part of the standard library, rather than an extension to the language. They build vector and matrix math libraries so that you can write some maths and have it resemble the actual equation. They build smart pointers, so they can stop forgetting to free objects - or worse, forgetting to bump the reference count of a reference counted object and exposing themselves to use-after-free bugs. Unlike in C, one can invoke a dynamically resizable array without carefully tiptoeing around integer overflow bugs. Key-Value containers exist in the standard library - C perhaps being the only language popular today not including such a fundamental datatype.
With discipline, individual bits of code can become clearer (due to greater abstractive power), though at the cost of it being tougher to understand the whole. It's not perfect - often the abstractions leak, and random bits of crud accumulate in these areas . Periodically, someone forgets that with great power comes great responsibility and a new Boost library is born.
Both sides continue to look at each other with suspicion. Each side thinks their code is more understandable and doesn't comprehend how the other can't see that.
It's a philosophical difference. Both sides look at the world from completely different perspectives.
Periodically and in spite of these disagreements, some major C project decides to convert to C++ , and some halfway house compromise between the two languages inevitably becomes the standard. The resulting codebase neither has the expressive clarity of C++ or the ease of reasoning of C. Neither side is happy with the outcome.
Both languages continue to be divided by a common syntax.
|||A C programmer might perhaps uncharitaby suggest that the number of bugs might be reduced by using a less complicated langauge, of course.|
|||std::enable_shared_from_this is perhaps one of the most prominent examples from the standard library|
|||GCC is perhaps one of the most prominent recent examples.|