tags:

views:

4277

answers:

23

A discussion recently ended laughing at the bad habits of programmers that have been too exposed to a language when they start programming in another language. The best example would be a Pascal programmer starting to #define begin { and #define end } when starting to write C.

Goal is to try to catch the bad habits of C programmers when they start using C++.

Tell about the big don't that you encountered. One suggestion by answer, please, to try to achieve a kind of best of.

For the ones interested in good habits, have a look at the accepted answer to this question.

+5  A: 

My favourite is the C programmer who writes a single method with multiple, optional, arguments.

Basically, the function would do different things depending on the values and/or nullability of the arguments.

RobS
Why should a C programmer do that, given that there are no optional arguments?
Philipp
Not *literally* optional - I mean the method would ignore some arguments and do something completely different based on others.. 1 function, many varied uses..
RobS
@Philipp: There's variable arguments, which is similar. That's how I interpreted it, even. E.g. a function like do_it(int what, ...) that inspects its first argument to figure out what to do, then reads other "optional" arguments as needed.
unwind
Thats an abuse that can be performed in any language. I can't see it as C/C++ specific - or even more common in C/C++
Peter M
Thank God I haven't seen something like that (yet).
Helper Method
I have seen that in reverse, C++ programmers wanting to use default arguments in C,anyway agree with Peter, it's not C/C++ specific and neither is a simple matter to decide about, I did a question about it http://stackoverflow.com/questions/3158482/specific-functions-vs-many-arguments-vs-context-dependent
Hernán Eche
+16  A: 

Not using the STL, especially std::string,

and/or

using std::strings and reverting to old c string functions in tight corners.

Binary Worrier
I get so confused when I read about the idea that people new to C++ struggle to use the STL. I'm new to C++, and the STL was one of the first things I jumped on. I just assumed it was the defacto standard library...
Stephen
I almost wrote the second part as an answer myself, but then I remembered that I do it myself sometimes. ;-) I know how to do things in both languages and pick whichever is easier in each case.
Jørgen Fogh
Binary Worrier
@Stephen: The STL (or however you want to call it) is *not* a de facto standard, but a de juris standard :)
FredOverflow
Binary Worrier
It's true that MFC doesn't really use the STL, but it *does* use a string class (CString), and so it should have occurred to him that there might be an alternative to C-style string handling.
dan04
If his only familiarity with string libraries was CString, it's no wonder he stuck with raw C-style!
Rob K
+43  A: 

Using raw pointers and resources instead of RAII objects.

Philipp
Amen. Precisely why I look at people funny when they complain about memory management in C++ - if they followed this one simple thing, memory management would be a non-issue.
Thanatos
@Thanatos The C++0x standard has brought to us std::shared_ptr, so yes, the memory management is cleaner now. But cyclical references still have to be avoided, so a decision has to be made between shared and weak pointers.I think it's presumptuous to declare memory management a non-issue.
Stephane Rolland
@Stephane Rolland: Perhaps - but perhaps another benefit of RAII outweighs that (rare) case: RAII is responsible for resource management, and can automatically handle not only memory, but locks, file handles, sockets, database connections, etc., without the programmer having to do extra work. Most other languages with garbage collection require the programmer to manually free (Python's "with", C#'s "using", etc.) most other resources.
Thanatos
@Thanatos, I do agree with you... (I am a HUGE fan of C++)... but may I warn you, if you don't question about cyclic references with std::shared_ptr, I guarantee you 100% that you will have memory leaks. It is not so rare as you think.
Stephane Rolland
@Thanatos: the *whole point* of `using` is so that the C# programmer *doesn't* have to manually free things like that...
RCIX
@RCIX: That is the point though: `using` *is* a manual free - not for memory, but for generic resources. Every time I "open" a resource that must be "closed" (anything implementing `IDisposable`), I must wrap it with a `using` - I must *remember* to write the code that will manually close or free the resource, thus, the burden of resource allocation and deallocation is still on me. If I forget, I've leaked at resource, at least until the GC gets it, which could be too late. `using` is just syntactic sugar for `free`, but it's still a free.
Thanatos
... RAII prevents this, allowing me to code the object's "closed" just once. RAII handles resources, whereas C#'s garbage collector only works well with memory.
Thanatos
@Thanatos: Manually freeing the object would be writing a try finally block and adding Dispose in the finally. Using takes care of that for you...
RCIX
@RCIX: But again, you miss the point. `using` is just a shortened `try, finally, Dispose` block, but *you have to remember to code it, each time, just like you have to remember to call free in C*. With C++ RAII objects, you don't have to remember to "write a `using` block", or something similar for the vast majority of situations.
Thanatos
+6  A: 

Not fully understanding the semantics of pointers and references and when to use one or the other. Related to pointers is also the issue of not managing dynamic allocated memory correctly or failing at using "smarter" constructs for that(e.g. smart pointers).

celavek
+27  A: 
  • using char* instead of std::string
  • using arrays instead of std::vector (or other containers)
  • not using other STL algorithms or libraries like boost where appropriate
  • abusing the preprocessor where constants, typedefs or templates would have been better
  • writing SESE-style (single-entry single exit) code
Frank
char * and arrays are nice and reliable. and a ton of a lot faster. ew. also what's wrong with SESE? (it's not even a C thing?)
Matt Joiner
If all you want is speed, go for assembly. 0-terminated strings and arrays without range checking are not "reliable", they are a shitload of pitfalls. And SESE is simply ugly and pointless. But yeah, SESE is not a C thing.
delnan
Why is it that these questions always contain the line *"One suggestion per answer, please"* yet someone always creates a list?
mizipzor
@Matt Joiner: It results in deeply nested, unreadable code and gives you false security, as the function can be left at any point where an exception can happen (and if it is just a bad_alloc), so potential cleanup at the end of function might never be executed.
Frank
@Matt Joiner. AFAIK the implementation of std::vector is just encapsulating a C-array. I have not checked it... but AFAIK the cost of using std::vector instead of C-array is close to NULL. Nonetheless I can understand that you C-traditionnalist may fear to learn novelty and to abide by the rigor of STL.
Stephane Rolland
@Matt Joiner string#length() executes in O(1), strlen() executes in O(n) - almost any operation on a string has to check its length. Second only arrays on the stack are any faster than std::vector it even supports direct access to the allocated memory.
josefx
What I'm trying to convey is that there is no need for religious flag waving when it comes to C++isms. Evangelically rewriting every C app in existence in C++ would not make the world a better place. Nor would bug fixes drop from the skies :). There is a time and a place for everything, fortunately C++ generally lets you choose.
Matt Joiner
STL is the recomended but you aren't bounded to it, char[] could be lighter (in some way) than inlude STL and use std::string, agree with Matt the nice of C++ is that let you choose ;) (@Matt using 2 AFAIK is duplicate code)
Hernán Eche
@Matt: Yes, rewriting working code is silly, but that's not what this question is about. *Continuing* to use raw arrays is a bad habit.
Dennis Zickefoose
In *very specific circumstances*, using bare `const char*` instead of std::string can cut out a bunch of overhead. I used to work on a command-line program, written in C++, with a whole bunch of static file-scope initialized data that included std::strings. Well, std::string has a constructor, which means file-scope std::string *executes code at startup*, even if the string is not going to be used this run. Converting all those to raw strings shaved a few hundred milliseconds off startup time.
Zack
@Zack: I am not against using anything low-level in said *specific circumstances*. But only after I profiled, and actually found a bottleneck. Everything else is premature optimization, which is the root of all evil, as we all know ;)
Frank
@Frank, I don't think using const char * when you know the string is const is premature optimization. In fact, it could be premature pessimization to not do so. But for non-consts, std::string all the way!
Rob K
@Stephane Rolland: "AFAIK the cost of using std::vector instead of C-array is close to NULL" not exactly right... sizeof (std::vector<int>) on my system returns 20, so there is overhead. Certain operation *may* result in non-inlined function calls, *certain* calls/methods in stl containers may result in abuse of dynamic memory allocation, and so on. Even accessing element in vector may result in method that calls method (compare with C array access). There ARE disadvantages, but they're compiler/platform/implementation specific, and you'll bump them only during profiling.
SigTerm
@Stephane Rolland: ..Also, as I understand it, STL containers weren't necessarily written to beat C arrays or something. They were made to provide default containers/algorithms so people won't be reinventing the wheel. Anyway, C vs C++ style coding is just an another pointless flamewar (same as Windows vs Linux). IMO, as long as program works, documented, readable and can be maintained, it doesn't matter how it was written - in C-style or C++-style. Abusing either style, or using only one of them exclusively will be probably a bad idea anyway.
SigTerm
@SigTerm: What platform are you on? That size seems odd unless there's debug info being stored. Other than that, you have a lot of mays that, in reality, don't exist. In practice, vectors *are* written to be at least as performant as dynamically sized arrays in C.
Dennis Zickefoose
@Dennis Zickefoose: Release build msvc prints 24. g++ prints 12. *"you have a lot of mays that, in reality, don't exist"* Proof? *"vectors are written to be at least as performant as dynamically sized arrays in C"* Proof? I saw posts on SO about vectors that don't release all memory on clear. I also saw a LOT of additional (iterators/operators) function calls when you work with any STL containers during profiling. IMO, the vector is an object that acts as array and has some warranties (automatic cleanup, linearly allocated memory, etc), but it still isn't a C array. It just acts like one.
SigTerm
@SigTerm: since C doesn't have a standard dynamic array, there is nothing to compare to a C++ vector. You can implement your own version however you want, in either language; if you don't need separate concepts of size and capacity, then its metadata will be smaller, but you won't be able to separate memory allocation from object instantiation; if you implement `clear()` to free the memory, then it will do so without having to swap with a new vector. In C++, you're often using types that must be created, copied and destroyed properly, and you really want containers to handle that for you.
Mike Seymour
@Frank: Don't use exceptions and you don't need to worry about them.
Matt Joiner
@SigTerm: I'd hardly call Windows vs. Linux pointless. Windows only has a large user base going for it. Linux has everything else.
Matt Joiner
@Dennis Zickefoose: There's hardly any such thing as a dynamic array in C. And vectors are not least performant as dynamic sized arrays. They're at _least_ one extra pointer deref slower (and that's being optimistic). Granted who cares, but you can't claim "it's better and just as fast" under any circumstances.
Matt Joiner
@Matt Joiner: "I'd hardly call Windows vs. Linux pointless" A lot of such discussions degraded into flamewars. Some of those went on for years. Often it goes like this: "A" makes sane polite argument. "B" makes sane polite counter argument. They start useful discussion, until C starts pillow-fight, which becomes a flamewar. Moderators step in for cleanup. And few months later another person ("F") makes same argument as A (because thread become long and reading everything was pain), and someone makes exactly same counterargument as B. The history repeats. IMO this is definition of "pointless".
SigTerm
@Matt: What, exactly, does `malloc` do, then? And what extra 'pointer deref' are you talking about?
Dennis Zickefoose
@Matt Joiner: Disabling exceptions? That causes all kinds of problem with code that uses exceptions, in particular the STL. And I consider the patterns that make code exception-safe good practice in general. RAII for example, and "committing" changes *after* the possibly failing calls. Even without exceptions I would prefer RAII and early returns (guards) over manual cleanup and SESE.
Frank
+8  A: 

Assuming said programmers have already made the mistake of attempting to learn C++:

Mistakes

  • Not using STL.
  • Trying to wrap everything in classes.
  • Trying to use templates for everything.
  • Not using Boost. (I know Boost can be a real PITA, and a learning curve, but C++ is just C+ without it. Boost gives C++ some batteries).
  • Not using smart pointers.
  • Not using RAII.
  • Overusing exceptions.

Controversial

  • Moving to C++. Don't do it.
  • Try to convert C stdio to iostreams. Iostreams SUX. Don't use it. It's inherently broken. Look here.
  • Using the following parts of the libstdc++ library:
    • strings (beyond freeing them for me, go the hell away)
    • localization (what the hell does this have to do with c++, worse yet, it's awful)
    • input/output (64 bit file offsets? heard of them?)
  • Naively believing you can still debug on the command line. Don't use C++ extensively without a code crane (IDE).
  • Following C++ blogs. C++ blogs carp on about what essentially boils down to metadata and sugar. Beyond a good FAQ, and experience, I've yet to see a useful C++ blog. (Note that's a challenge: I'd love to read a good C++ blog.)
Matt Joiner
+1 for having the bottle to write this.
JeremyP
Haha thx. Truly I love C++, because everything else is worse. But it's no excuse to wave flags and chant.
Matt Joiner
Could you elaborate on what you mean by "libstdc++"? Do you mean "the bits of the Standard Library that aren't based on STL or Boost" (which you say should be used)? Or something else?
Mike Seymour
+1 for calling out iostreams.
Stephen Canon
trouble is stdio also sucks
jk
Whats broken about iostreams?
Nils
@Nils: the main issues are that formatted I/O (using `<<` and `>>`) provide rather quirky error handling, and because of their use of the localisation library are usually a lot slower than the equivalent `stdio`-style formatting.
Mike Seymour
stdio is alright, some parts of it are just a bit aged. it's a damn sight better than iostreams. use a format printf checker (such as is builtin to GCC (default on stdio funcs, add to your own with `__attribute__((format(printf)))`, or MSVCs runtime checks on the parameters given), and RTFM. iostreams was never necessary in the first place, and lacks half the functionality of stdio.
Matt Joiner
IOStreams contains one important feature the C library lacks: extensibility. Oh, and built-in type safety.
Dennis Zickefoose
@Dennis Zickefoose: You mean like this? http://www.gnu.org/software/coreutils/manual/libc/Customizing-Printf.html#Customizing-Printf and wrapping things (the way you'd do in C++ on a large project anyway)? At least with C's stdio you can "drop out" into the raw system calls and back up. Once you go iostreams, you're stuck.
Matt Joiner
"Portability Note: The ability to extend the syntax of printf template strings is a GNU extension. ISO standard C has nothing similar."
Dennis Zickefoose
I wonder why nobody standardized a printf-style function for binary I/O. It would be very helpful to be able to use templates string to read/write structures from/to explicitly-specified binary formats.
supercat
@supercat: I'd model it on this: http://docs.python.org/library/struct.html
Matt Joiner
@Matt Joiner: That looks almost exactly like what I had in mind ~17 years ago when I was lamenting the lack of a standard binary-I/O equivalent of scanf/printf, though I've also just started pondering some macro abuse to automagically generate straight-line code to pack and unpack structures.
supercat
@supercat: Abuse, abuse!! DO IT (and link me it'll be a nice read).
Matt Joiner
@Dennis Zickefoose: Take a look at the link I put in the answer regarding iostreams. Just some food for thought.
Matt Joiner
I've never been linked to anything in the FQA worth reading. This was no exception.
Dennis Zickefoose
The important thing about C++ iostreams is that they're completely broken from an i18n/l10n perspective. When your message is << broken << up << like << this, you don't have the full sentence to substitute with localised copy. If the other language uses different word order or plural forms (i.e. just about all of them), you're screwed. printf, OTOH, lets you put numeric placeholders into the format string, which let you reorder things for different languages.
Jack Kelly
Ah yes, the "give me an IDE or I cannot debug to save my life" approach. D'oh, if you don't know your way around GDB, you can get far - but once you start remotely debugging a running server process, GDB is your friend. Use insight or ddd if you have to, and your beautiful IDE whenever you can get away with it, but for seriously crufty stuff you *need* at least basic GDB skills. Actually, with some experience and a second terminal for reference, you need nothing else.
DevSolar
@DevSolar: I'm the CLI kind. Debugging C++ is ugly no matter what you use. Trying to "dive in" to large C++ projects is incredibly painful due to the excessive typing and indirection the language (and zealous fans) employ. Debugging C by comparison, is a breeze, I have a few terminal windows, and geany.
Matt Joiner
@Matt Joiner: Check out http://sourceware.org/gdb/wiki/STLSupport - GDB helper configs for handling STL containers et al.
DevSolar
+14  A: 

using pointers instead of references

Jens Gustedt
it is not possible to have std containers of references, so the use of pointers is still part of the core of standard C++.
Stephane Rolland
So better would be:Not abiding by the rule, "Use references when you can, and pointers when you must."
Ben
+14  A: 
  1. Writing class definitions that are 2000 lines of code.
  2. Copying and pasting that class definition into 12 different places.
  3. Using switch statements when a simple virtual method would do.
  4. Failing to allocate memory in constructor and deallocate in destructor.
  5. Virtual methods that take optional arguments.
  6. Writing while loops to manipulate char* strings.
  7. Writing giant macro's that are a page in length. (Could have used templates instead).
C Johnson
Most of these sum up the issues I've dealt with.
sheepsimulator
As I can see we have all suffered the same plagues...
Stephane Rolland
+6  A: 

Making everything in a class public. So, data members that should be private aren't.

zooropa
When they make everything public, they are coming from C. When they write getters and setters for every variable just out of habit, they came from Java...
DevSolar
+12  A: 

Very experienced developers not understanding casting or even object oriented programming:

I started helping out on a project and one of the senior guys was having a problem with some code that used to work and now didn't.

(Class names have been changed to protect the innocent, and I can't remember the exact names) He had some C++ code that was listening to incoming message classes and reading them. The way it had worked in the past was that a Message class was passed in and he would interogate a variable on it to find out what type of message it was. He would then C-style cast the Message as another specialised class he'd written that inherited from Message. This new class had functions on it that extracted the data how he wanted it. Now, this had been working for him fine but now was not.

After many hours looking through his code he could not see a problem and I had a look over his shoulder. Immediately I told him that it's not a good idea to C-style cast Message to a derived class which it was not. He disagreed with me and said he'd been doing it for years and if that was wrong then everything he does is wrong because he frequently uses this approach. He was further backed up by a contractor who told me I was wrong. They both argued that this always works and the code hasn't changed so it's not this approach but something else that has broken his code.

I looked a bit further and found the difference. The latest version of the Message class had a virtual function and hadn't previously had any use of virtual. I told the pair of them that there was now a virtual table and functions were being looked up, etc, etc.... and this was causing their problem, etc, etc.... They eventually agreed and I was presented with a comment that I will never forget: "Virtual completely screws up polymorphism and object oriented programming".

I forwarded them a copy of a decorator pattern as an example of how to add a function to an existing class but heard nothing back from them. How they fixed the idea I have no idea.

Matt_JD
hehehe, `vptr` is always waiting in the dark, to stab you in the back :) it usually does this after you proclaim "C compatibility, i has it!"
Matt Joiner
"Virtual completely screws up polymorphism and object oriented programming." - What! I'll never forget that too.
Donotalo
Those programmers should have been fired.
C Johnson
+8  A: 

Using C-style casts.

C++ allows you to independently choose whether to allow casts between unrelated types, and whether to allow changes to const and volatile qualifiers, giving considerable improvements to compile-time type safety compared with C. It also offers completely safe casts at the cost of a runtime check.

C-style casts, unchecked conversions between just about any types, allow whole classes of error that could be easily identified by more restrictive casts. Their syntax also makes them very difficult to search for, if you want to audit buggy code for dubious conversions.

Mike Seymour
this catches a lot of stuff. in addition when knowingly changing POD widths, you can use `numeric_cast` if you can afford the overhead.
Matt Joiner
A: 

Not leaving well enough alone, and using C instead.

Matt Joiner
+1 My God, have you seen the **stones** on this guy? <crowd_mutters>Wow, just look at the size of that mans testicles|Have you ever seen NADS that huge|My, his girl must just love those nuts</crowd_mutters>
Binary Worrier
Repeating yourself is a bad habit in any language.
Mike Seymour
Well it _is_ one habit per answer, and my other answer contains several.
Matt Joiner
+11  A: 

One word: macros. I am not saying macros have no place at all in C++, but former C programmers tend to use them way too much after they switch to C++.

Nemanja Trifunovic
#define, especially in header filesuse enum's for #define constants; use inline methods or templates for #define macros.
franji1
@franji1: And there's still no good substitute for them in conditional compilation, if you need that.
David Thornley
Agreed - best to minimize scope to one .CPP file (not header file). If it needs to be in a header file that clients include, make sure it's "as unique as possible" (yeah, I know, what does THAT mean). ALL_CAPS_HELP_AS_THE_ACCEPTABLE_POUND_DEFINE_FORMAT, but as we all know, that's as good as a rule as appending xyzzy_42_foo_bar to all your #defines. Or Microsoft's common implementation... #ifdef _UNICODE #define GetLength GetLengthW #else #define GetLength GetLengthA #endif :-D
franji1
+5  A: 

Writing using namespace std because everyone does and then never reflecting on its meaning. Or knowing what it means but saying "std::cout << "Hello World" << std::endl; looks ugly".

Gunnar
it's a big trap for people who skip c. they don't appreciate the reason for namespaces, and furthermore every c++ tute contains the terrible use of iostreams that puts you off c++ for life. why don't they start with printf? trying to explain `<<` and `>>` to noobs and pros alike is pointless.
Matt Joiner
+2  A: 

Not using templates when creating algorithms and data structures (example). It makes things either too localized or too generic

I.e. writing

void qsort(MyStruct *begin, size_t length);  //too localized
void qsort(void *begin, size_t length, 
           size_t rec_size, int(compare*)(void*,void*));  //too generic

instead of

template <class RA_Iter>
void qsort(RA_Iter begin, size_t length);
  //uses RA_Iter::value_type::operator< for comparison
Pavel Shved
How about std::sort() ?
DevSolar
@DevSolat, the bad habit you're referring to is discussed in the other answer.
Pavel Shved
+11  A: 

Adding using's into header files so they can avoid names like std::string in type declarations.

JaredPar
Beautiful answer!!!
C Johnson
"using" in header files is a terminal offense.
DevSolar
+6  A: 

Passing objects with pointers instead of references. Yes, there are still times when you need pointers in C++, but references are safer, so you should use them when you can.

Chris
Yep this is something I also did not learn automatically.
Nils
+22  A: 

Declaring all the variables at the top of a function instead of as close as possible to where they are used.

jeffm
a pet peeve of mine :)
Matt Joiner
i don't exactly know why, but i always do that. :( it feels good for me.
Donotalo
God bless you my child.
C Johnson
I knew an ex Fortran programmer who did that in Java. :-/
stesch
Imagine a loop that reads a file one line at a time. You create a loop that reads in a string via cin, and then processes it in some way.If you declare the string variable "as close as possible to where it's used," which is inside the loop, it will slow down your program because it will invoke the string's constructor each iteration through the loop.If you declare the string variable at the top of the function, it will only invoke the constructor once, and it will be faster.
fish
@fish ... "as close as possible," but not closer!
HaskellElephant
@fish: There are some subtleties to this, certainly. I was just trying to make a broad point.
jeffm
+1  A: 

Confused uses of structs vs. classes, overuse of global methods that take object pointers as arguments, and globally-accessible instance pointers, a la:

extern Application* g_pApp;
void RunApplication(Application* app, int flags);

Also (not saying it's totally useless, but still):

const void* buf;
Shotgun Ninja
+2  A: 

Well, bad program design transcends languages ( casts, ignoring warnings, unnecessary precompiler magic, unnecessary bit-twiddling, not using the char classification macros ) , and The C language itself doesn't create too many "bad habits" ( Ok, Macros, esp from the stone ages ), and many of the idioms translate directly. But a few that could be considered:

Using a feature just because it's in C++ and so therefore it must be the right way to do something. Some programs just don't need Inheritance, MI, exceptions, RTTI, templates ( great as they are ... the debugging load is steep ), or Virtual class stuff.

Sticking with some code snippet from C, without thinking if C++ has a better way. ( There's a reason you now have class, private, public, const (expanded beyond C89) , static class funcs, references.

Not being familiar with the C++ i/o lib ( its BIG, and you do need to know it) , and mixing C++ i/o and C i/o.

jdu.sg
I don't agree with the last 2 paragraphs, but +1 for the first 2 :)
Matt Joiner
@Matt joiner thanks, I think that's one of the neat things about C++ - everyone ( or every project ) gets to draw that line between "Useful" and "Not useful" almost wherever they think appropriate. Want to use the C subset, fine. Want to add classes, great. Want to avoid c++ io ... well, you need a good reason for that ;-)
jdu.sg
+2  A: 

He thinks that C++ is just a little more different language from C. He will continue programming C masked by C++. No advanced use of classes, the structs are considered less powerful than classes, namespace, new headers, templates, nothing of these new elements are used. He will continue declaring integer vars without int, he will not provide functions prototypes. He will use malloc and free, unsafe pointers and preprocessor to define inline functions. This is just a small list ;)

Charlie
+1  A: 

Declaring all the variables at the start of the function itself even if the variable will be used only after 100 lines or so.

Happens especially for local variables declared inside a function.

liaK
A: 
  1. Solving the problem instead of creating a class-based monstrosity guaranteed to keep you in health insurance and 401K benefits.

  2. Implementing lisp in a single file and doing the design in that.

  3. Writing normal readable functions instead of overriding operators?

  4. Writing in a style which can be understood by the junior programmers which see good practice as "not writing in C++".

  5. Talking to the OS in it's own language.

WarWeasle
I fully understand your message. But please note that I do not consider C++ as any better than C. They are just different. I mean really different. Your sarcastic answer, albeit perfectly valid and brilliant for a C/C++ comparison does not match the question.
Didier Trosset
This answer is awesome. Especially point 5. Wrapping perfectly good C libs/syscalls in meta junk is a pet hate of mine.
Matt Joiner