Slashdot Mirror


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.

9 of 37 comments (clear)

  1. The one I keep running into: Polymorphism. by Christopher+Thomas · · Score: 3

    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.

    1. Re:The one I keep running into: Polymorphism. by StandardDeviant · · Score: 5
      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 sounds like a perfect place to use the STL and/or C++'s templating mechanism. Trust me, I'm not a huge C++ fan, but the container classes in the STL kick ass (I imagine something like what you describe is already there). Even if the STL don't give you no lovin', templates (and references) make it really easy to write a storage class that works over an arbitrary range of types.

      This is just my 2 cent's worth. I'm mainly a C guy too, but the STL was the single biggest thing tempting me to switch to C++.

      There is good coverage of all this in Bruce Eckel's Thinking in C++ (and other such as the C++ Primer by Lajoie et al.) I mention Bruce Eckel's books because they're available to peruse online, his site is mindview.net which unfortunately seems to be down right now (maybe it's hosted in california ;-). I found a mirror of his C++ books in PDF form here and a mirror of all his books in HTML form here. If you're like me you'll read the book(s) online and end up liking them so much you want to own a paper copy (and here I make my standard reference to bookpool for discount tech books).


      --
      News for geeks in Austin: www.geekaustin.org
  2. The Java subset by geophile · · Score: 3
    I did C++ for many years and I'm now much happier in Java. I have thought about what C++ features I'd use and not use if I had to go back, and I think I'd restrict myself to the Java subset. So I'd include polymorphism, single inheritance and access control (private, protected public). I'd throw out pointer arithmetic, operator overloading, and templates. I might even avoid embedded objects (e.g. class A { B b; };). Maybe use a limited form of multiple inheritance, simulating Java interfaces.

    I really think that Java got it right.

    1. Re:The Java subset by bmckeever · · Score: 3
      A few comments:

      0: You didn't mention the parts that Java got wrong, like the effed-up Collections API (not type-safe), not having deterministic destructors (finally is a clumsy substitute), and not having a const modifier (with semantics different than final).

      1: Why would you throw out templates? They are powerful, and generic code is much better than cut-and-paste programming.

      2: It can be dangerous to think of C++ and Java as being almost the same. Syntactically, they have much in common, which can lull you into thinking they are more similar than they really are. But they are different, and if you regularly switch between them, you can find the gotchas (or they can find you).

      --
      Your favorite .sig sucks
  3. my list of good and bad C++ by dutky · · Score: 3

    The good parts:

    • inheritance: if you're not using this then why bother with C++ at all?
    • class polymorphism: this goes hand in hand with using inheritance.
    • exceptions: even though they aren't supported by many of the low level libraries, they make the code much easier to read.
    • templates: even though the standard isn't entirely reliable on all compilers and they are a bit mystifying to newbies, they fit very well with the OO philosophy.

    The bad parts:

    • overloading: using the familiar language operators to do double (and often tripple) duty is just plain confusing in real code. It looks really cool in language demos, but doesn't work for real world projects. When you include both function overloading and default parameter values, you get an unmanagable mess.
    • stream I/O: for the same reason that operator overloading is a crock, so is stream I/O. I quote "I saw cout shifted "Hello World" times to the left and stopped right there."
    • references: most of your programmer's time will be spent reading the code rather than the class definitions (and this is as it should be) so anything that makes it more difficult to tell what is happening in the code is bad and to be avoided. References are just such a beast, especially when used in parameter lists. (As a return value they are almost acceptable)
  4. Pretty simple, really. by rjh · · Score: 3

    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.

  5. C++ Resources you should check out by Greyfox · · Score: 3
    There are some things that will bring your coding to the next level. The first and foremost of these is "Design Patterns." Shell out some cash and get the book. It's so worth it it's not even funny.

    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?

  6. Coding practice by ZeroConcept · · Score: 4

    My experiences with a 2,000,000 lines of code C++ server project (in winNT):

    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/5resour ce.html).
    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.

  7. re: C++ coding practices by bmckeever · · Score: 3
    It all depends on the team. If everybody on the project is familiar with feature X, then use it where appropriate, even if it's a tricky feature (eg exception handling). If the Right Way calls for a feature that your colleagues understand, then by all means, do it the Right Way. However, the Right Way that leaves the next guy scratching his head is not the true Right Way. On the other hand, I'm not sure it's reasonable for somebody who doesn't have a basic understanding of exceptions and their use (and dangers) to call himself a C++ programmer any longer.

    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 .sig sucks