There are already a lot of good answers. Mine will be more "mindset oriented".
Data vs. Action!
- In C, everything is done to think like "Apply this effect to this data".
- In C++, this is more like "Data should behave".
While the "Data should behave" can be done in C (and it is done!), in C++, everything needed to implement this easily is already accessible : Encapsulation, constructors, overloading overriding, templates, etc..
I found this "Data should behave" idea a very good guiding principle when coding in C++.
C++ syntactic sugar is not optional
You'll find a lot of C++ features that could be done in C, and some people use it as an excuse to not learn them. This mindset is dangerous (this is the part "treat C++ as a new language, and not an extension" seen in some posts).
A side effect of avoiding writing C++ the C++ way is that while a C++ developer is supposed to understand C++ code, he/she is not supposed to understand your little personal framework mimicking C++ sugar with C-only features. In fact, he/she won't be interested by your framework. Truth to be said, he/she will only feel pity/contempt for you because you lost precious time producing that. Ultimately, he/she will hate you if he/she must use your framework instead of the C++ sugar.
Guiding principles like "I can do this the C way" will just make you miss the wagon. Better not to start learning C++ at all if you already have this kind of C-centric mode of thinking.
Your language of choice is never the best. YOU are supposed to become the best. If you write C++ code, then write it the C++ way.
C-compatible C++ code is a semantic error
Typedefing your structs to make them compilable by a C compiler is a bad joke. Using pointers instead of references is a slap to your future self. The extern "C"
will only make your code weaker, not stronger. And using void *
for genericity will only increase the number of fellow C++ coders who will gladly pay to have your head removed in a spectacularly painful way.
Don't ever bother to write C-compatible code unless you really really really have to.
You'll just weight yourself down with a time-consuming coding style for a feature you'll never use.
The compiler is a powerful friend/enemy
Working low level has strange effects on some developers. They believe a lot on their control of the compiled code. Delegating this control to higher-level constructs is difficult for them.
A good example of that is ditching the constructor/destructor pattern because "sometimes, constructors takes too much time... Better to do it my way...".
The C++ compiler is quite able to optimize apparently unoptimized code. In fact, the code produced by the compiler can be quite different from the one you believe you produced.
Don't try to be better/smarter than the compiler is because:
- You probably already lost the fight, as even old compilers will usually produce better code than you can dream to do today
- Even if you did win the fight today, it will automatically turn into a defeat tomorrow, as compilers will become better and better in the future, so your "optimized code" of today will become the program bottleneck and refactoring subject of the next years (not mentioning shameful memories for you).
So, trust your compiler.
Don't micromanage the production of your code. Do your own work, and let the compiler do its own.
Note that this point should not be used to justify production of slow/inefficient code. If premature optimization is the root of all evil, you must still use your knowledge of the language and the compiler to produce good and efficient code (see the next point).
Know the advantages/drowbacks/costs of each C++ construct
For example, the fact virtual methods adds one indirection to the function call means for some people that performance will decrease dramatically. Truth is, performance problems are often elsewhere.
Ignorance is no excuse.
Know the code produced for each C++ construct (i.e. inlining, references, constructor, destructor, exception, function overload, function override, template, virtual function, etc.). Know what will be optimized away, and what won't.
This way, not only you won't pay for what you don't need (this is a guiding principle of C++), but you will also profit from what costs you zero but brings you a lot.
Be humble
There are people doing research in C++ that were better at C++ the day of their birth than most of us will ever be. Even if we ignore Stroustrup, names like Meyers, Abrahams, Alexandrescu, Sutter, etc. regularly crop up alongside new ideas. Despite (or as a consequence of) its alien outlook, STL is revolutionary library. And a library like Boost, despite its "small size" when compared to some complete frameworks (like Java or .NET APIs), is a massive repository of excellent code offered to you to study.
Just because you find some new feature "strange" or "alien", don't underestimate it. Trying to understand it will PERHAPS bring you another tool at your disposal, and will ALWAYS increase your mastery of the language, and will ALWAYS make your brain work, which is a good thing in the dev business.
Most people I know who failed their "conversion to C++" just assumed this or this feature was useless because they did not bother to understand it.
If you don't know what it is, learn it.
Without RAII, your C++ code is just bugged code that avoided compilation error.
RAII is the single most important notion of C++.
Everything else is related.