From Schmid.wiki
Jump to: navigation, search

C++ lacks a proper coding standard. This standard is not perfect, but it is a useful set of guidelines. Here is a list by Andrei Alexandrescu, author of 'Modern C++ Design'. The Code Conventions for the Java Programming Language are also relevant.

I have compiled a set of rules, which are more or less the de facto standard of the C++ community.

The Most Important Rule

Follow the style of the project you're working on or the toolkit you're using. Not following the style of the project you're working on makes the code significantly less readable, due to the mixing of different styles in the same program. This rule should be a no-brainer.

E.g., if you use Ogre, you should have:

Entity        - upper camel case classes
getMesh       - lower camel case functions
mMesh         - member variables prefixed with 'm' (Hungarian style?)
BIND_ORIGINAL - literals and constants in all caps with
                underscores at word boundaries

The Mozilla project uses this style, except class names are lower camel case.

Or if you developing a wxWidgets application, you should have:

MyApp         - upper camel case classes
CreateFrame   - upper camel case functions
m_Mesh        - member variables prefixed with 'm_' (Hungarian style?)
BIG_FRAME     - literals and constants in all caps with
                underscores at word boundaries

The following rules are employed when your project does not dictate your style.

Naming Style

The C++ standard library and the Boost libraries use the following standard:

My_lexer      - upper case underscored classes and namespaces
for_each      - lower case underscored functions
icase         - lower case underscored constants
DO_STUFF      - preprocesser macros should be all caps and underscored

Apparently, studies show that underscored literals are easier to read than camel case. Bjarne Stroustrup also hinted at these studies in his talk: C++0x - an overview. It certainly makes sense; if spaces were superflous, we would stop using them in normal text. They are not, our brains need them. And I think most would agree that underscores are more reminiscent of spaces than the case changes in camel case. And to illustrate the readability:

This_should_demonstrate_which_naming_style_is_the_most_readable

thisShouldDemonstrateWhichNamingStyleIsTheMostReadable

However, underscores have been overwhelmed by camel case as of late, and some programmers may be uncomfortable with the standard C++ style. Also, I think that many choose camel case because they think it looks cooler. In my opinion, the readability argument and the fact that this style is used in the standard library and the Boost libraries outweights the other factors, and thus underscores should be employed.

Source Layout

class File_reader {
    int some_method(int some_parameter);
};

...

my_file_reader = new File_reader();

File Naming

Most of the Linux world, including GNU uses the following naming standard:

  • A header file containing the class definition 'Foo' and support functions should be named 'foo.h' (lowercase and .h)
  • The implementation file for the class 'Foo' should be named 'foo.cpp'

The Mozilla project (Firefox a.o.) uses camelCaps file names and .cpp / .h extensions.

However, Boost use .hpp for headers, and separate words with underscores, e.g.: cpp_regex_traits.cpp.

Documentation

Use Doxygen for documentation. Use the JavaDoc style for easy migration to and from Java. Use Graphviz for the Doxygen graphs. Install it and enable it in the Doxygen configuration file:

HAVE_DOT = YES

Here's an example file header for a header file defining a 'Creature' class. '@sa' is an abbreviation of 'see also':

/**
 *   @file     creature.h
 *   @author   Jakob Schmid
 *   @date     commenced 2005-05-20
 *   @date     last changes 2005-05-20
 *   @note     This is a test.
 *   @warning  Usage of this class may provoke boredom.
 *   @sa       http://www.whatever.org
 */

... and an example class definition with documentation. Note the use of LaTeX math:

/**
 * Just a test class.
 * Does nothing, really.
 */
class Creature {
public:
    Creature(void);  ///< Constructor that outputs info.

    /**
     * Calculates age from size.
     * Right now, it just returns @f$ \frac{size}{2} @f$.
     * @param size The size of the creature, measured in feet.
     * @return The age of the creature, in years.
     */
    int calculate_age(int size);
};

Header Files

All header files should have preprocessor guards, for instance, if your class is called 'FileReader':

#ifndef SOME_PROJECT_FILE_READER
#define SOME_PROJECT_FILE_READER

...

#endif

References