Where Should You Apply Various C++ Coding Practices?
Dr. Love asks: "C++ contains a mountain of features. I am searching for a good C++ coding practice - what language features to avoid, what language features to make extensive use of, etc. In my survey of C++ coding practices, there seems to be a plethora of philosophies ranging from the stingy to the highly abstracted and elaborate. By stingy, I'm referring to those that use few of C++'s advanced features, such as Mozilla.
At the opposite end of the spectrum, there are elaborate practices
that make extensive use of the STL, exceptions, RTTI, templates,
etc. Those who prefer the simple implementations tend to argue that
elaborate practices result in inefficient, unclear, and unportable
code. Those who prefer the elaborate implementations tend to argue
that simple implementations are missing out on a Nirvana of reuse and
clean design. Are these arguments unfounded? What has been your
experience with C++ coding guidelines? What does the industry expect?" Just like the choice of the language itself, the choice of the features you use in your language should lend itself to the task you are developing. Some projects don't need to use every single feature of C++ to get the job done, however use of those ignored features in other projects might make your life (and your code) much easier to handle.
The feature that crops up in practice most for me is polymorphism.
I code mainly in C, not C++. I've just written yet another program that uses a binary tree to store several different types of data. The naive way of writing this is to make several different tree-node types and several sets of nearly-identical tree manipulation functions. The way I did it was to kludge things with a data type identifier and a union of the possible data stored.
The Right Way to implement this is to make an abstract class for the tree node, write the tree manipulation methods to work with the abstract class, and make derived classes that store different types of data, with appropriate constructors that initialize the data fields. Anything that doesn't have to care about the data type can just manipulate the objects as the original abstract class.
This situation has cropped up before. Any situation where I'm doing the same type of thing with many types of data can benefit from derived classes and polymorpism. This happens frequently with utility libraries that I write, but also crops up now and then with certain types of information storage task.
I still code in C most of the time, because I'm too lazy to dust off my C++ books and these are just my own projects. However, this is indeed a common set of cases where features of C++ would be useful.
I really think that Java got it right.
The good parts:
The bad parts:
C++ is, like Perl, such a mess because the problem set is such a mess. That means it's pretty easy to shoot yourself in the foot--and given C++'s power, shots to the foot often take off everything below your waist.
If crossplatform, portable code is a necessity, then be very careful when using newer features such as templates. I've had the devil's own time taking code that works perfectly fine in GCC-2.96 (the Red Hat snapshot, which is a very fine C++ compiler), but breaks horribly under GCC-2.91. Code that compiles cleanly under MSVC++ will oftentimes break horribly in GCC-2.96, etc.
The fewer C++ features you use, the less chance you'll run into these gotchas. That's why the Mozilla team uses a restricted set of C++ functions, I think, far more than to enhance readability or whatnot--the simple fact is, the more C++ features you use, the harder it is to get it to compile under Foo compiler, because Foo doesn't properly implement such-and-such chapters of the Standard; and code written for the Foo compiler breaks on the Bar compiler, because Bar demands strict adherence to the spec, which Foo doesn't provide.
That being said: give consideration to at least using the inheritance features of C++'s class system. Inheritance is, if anything, the most useful feature of C++, and is well-supported by every compiler. Don't treat C++ like Ada83, where classes existed only to protect data as private and to create interfaces to other bits of functionality; let your C++ classes be hierarchial, let them inherit from base classes, and use that to your advantage.
After that, I don't have any recommendations. I'm personally a big fan of generic programming (templatized programming) and the STL. The STL is fearsomely efficient and fast. It's got a learning curve like the Matterhorn, but once you climb it, it's wonderful.
BTW, if anyone tells you to ignore templates on grounds that they cause bloat, please check out the home page of Amit Patel, a Doctoral student at Stanford (who, I believe, often reads Slashdot--if so, hi, Amit, drop me a line sometime) and friend of mine. According to benchmarks he provides on his page (click here), templatized code that makes use of the STL is often, if not almost always, of comparable executable size to an equivalent C program, and substantially faster.
Some compilers, such as Sun's, are absolutely awful with templates--that's probably how the nasty myth of templatized code being bloated and slow came to be. As a rule, though, there's no general truth to this myth; some compilers produce bloated code when using foo, bar and baz parts of the language, but it's not a characteristic of the language--just a characteristic of a crappy compiler.
Next is the STL. The STL is a fairly recent newcomer to C++ as are templates themselves. The STL can save you a lot of time that you'd spend reimplementing the same data structures. It's an excellent resource. There are other cool things you can do with templates as well -- the GTK-- signal system is way cool, for instance.
Finally, check out here (http://hjem.get2net.dk/nimrod/tipdesign.htm for the goat wary.) It's a bunch of archived articles from the C++ netnews group. There are plenty of good coding practise pointers and code snippets and it's a great resource.
These three resources should get you well ahead of the curve when it comes to making good use of the C++ features.
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
My experiences with a 2,000,000 lines of code C++ server project (in winNT):
r ce.html).
.
1) ALLWAYS use SmartPointers unless you have a compelling reason to not use them.
2) Memory leaks are going to be your biggest problem, see rule number 1.
3) Use ASSERT like crazy...everywhere, if you are expecting some valid imput in a method, make sure it's explicilty stated with an ASSERT. ASSERT is the best way to catch an error on the spot.
4) Make the compiler generate debug symbols in release as a separate file, you WILL find bugs that only happen in RELEASE versions.
5) Use boundschecker to debug memory problems.
7) Don't use catch(...) on any other place than your main function...if you need to, rethrow the exception and let the debugger catch it. Never catch an exception that you don't know how to handle on the current scope.
6) Make your code exception safe, it's the only way to deal with memory exhaustion problems(http://www.relisoft.com/book/tech/5resou
7) If you are using multiple threads and a large number of locks, use smartlocks, otherwise you will have deadlocks (it's painful but does pay off).
8) If you application is multithreaded, use a static locking order, otherwise you will have deadlocks.
9) NEVER, NEVER, NEVER create your own collections or strings, use STL.
10) If you use Visual C++ and STL, make sure you replace the source files with the fixed versions(http://www.dinkumware.com/vc_fixes.html)
11) Read "Effective C++" and "More effective C++" (look them up in amazon)
12) Avoid Runtime Type Identification, most of the times you don't need it.
send me a message at andresmurillo@go.com if you need more info.
On the other hand, forbidding a feature (like templates) just because it's complicated can be stupid and self-defeating. Are you really writing your own Map class? Are you sure it's right? What do you do when you need a Map from Foos to Bars, and the only one you have is from Bazes to Quuxes? You don't copy and paste, do you? And your Map doesn't subvert the type system, right? And if you decide you should be using a Set instead of a List, you can fix this with one line of code, right?
Your favorite