C++ Code Style Guide

The purpose of this style guide is to provide a starting point for writing code in C++. The guide should be followed as closely as possible; however, when interfacing with external software and libraries, it can be sometimes be useful to follow their style.

This style guide is loosely based on the Qt Coding Style guide.

Remember

Consistency is paramount.

Documentation

Any documentation will be generated from source and header files (using doxygen). You document for other developers and users of your classes, not for yourself.

In header (.h) files, document interfaces. That is; document what the function does, not the implementation.

In implementation (.cpp) files, you can document source code where the operation is not obvious.

Formatting

Whitespace

  • Use 2(two) or 4(four) spaces for indentation, no tabs. (Choose one option and be consistent).

  • Use blank lines sparingly and only to delimit functions, or related statements.

  • Use only one blank line.

Line Breaks

  • Keep lines shorter than 100 characters.

  • When flowing onto a second line, commas go at the end of the broken line.
    e.g.

    int result = function(argumentOne, argumentTwo,
          argumentThree, argumentFour);
  • Similarly, operators start a new line.
    e.g.
    int result = functionOne() + functionTwo()
          + functionThree() + value;

Comments

  • Prefer Doxygen comments for functions.

  • Use inline comments above code to describe any unobvious code.

  • Only use a single space after the comment delimeter (// or /*). Exception: multiple spaces can be used to align text in multi-line comments.

Braces

  • In general, place the left curly brace { on the end of the opening statement line.
    e.g.

    if (x == 2) {
      y = 7;
    }
  • Use braces for all if else blocks.
    e.g.
    if (isZero) {
      x = 7;
    } else {
      y = 7;
    }

Pointers and References

  • Use a single space befor an * (asterisk) or & (ampersand), but never after. e.g. int &number = i;

Parentheses

  • Do not use spaces between function names and parentheses. e.g. function(); not function ();

Conventions

Headers

  • Use #ifdef header guards.

  • Prefer verbose argument names in headers. Rationale: Most IDEs will show the argument names in their completion-box. It will look better in the documentation.
    Bad style:
    int doSomething(std::string n, char i);

    Use this instead:

    int doSomething(std::string name, char initial);

Casting

  • Use C++ style casts (static_cast, reinterpret_cast, dynamic_cast, etc).

  • For fundamental types, use constructor form.
    i.e.
    int b = int(a);

Things to avoid

  • Don't use C style string manipulation - prefer STL string types and functions.

  • Don't hide virtual methods in subclasses.

  • Don't shadow class variables. i.e. Avoid this:
    void setName(std::string name) {
      this->name = name;
    }

    Use this:

    void setName(std::string newName) {
      name = newName;
    }

Coding

Some of this section is blatantly ripped off from the isocpp.org faq.

  • Use preincrement and predecrement over postincrement and postdecrement wherever possible. i.e. ++i; instead of i++;

  • Minimise evaluation - avoid recalculating values, especially in loops.

  • Do not use goto unless it is the only way to achieve the desired operation.

  • Keep C-style [] arrays out of class and function interfaces

  • Avoid unions

  • If you have any doubts about the validity of a pointer, use a smart pointer instead

  • Don’t use “naked” new and delete (use containers, resource handles, etc., instead)

  • Don’t use ...-style variadic functions (“printf style”)

  • Avoid macros except for #include guards

Naming

Variables

  • Use descriptive names. Exception: short names may be used for limited scope variables, e.g. loop counter, function return temporaries.

  • Use camel case, starting with a lower case letter.
    e.g. variableName

Functions

  • Use camel case, starting with a lower case letter.
    e.g. functionName

Classes

  • Use camel case, starting with an upper case letter.
    e.g. MyClass

Class Member Variables

  • Use the _ (single underscore) prefix convention for private member variables.

Enumerations

  • Use camel case, starting with a capital letter, this applies to both the enum name and the values.
    e.g.
    enum MyEnum { ValueOne, ValueTwo, ValueThree };

Declarations

Classes

  • Use class instead of struct. Exception: struct can be used when creating data types for interoperation or passive data only objects.

  • Declare access sections in this order: public, protected, private. Rationale: The public section is of interest to every user of the class, the private section is only of interest for the implementer of the class.

  • Do not declare global variables in the class header. If a variable is needed for all members of a class, use a static member.

  • Do define overload operators like ==, =, and <<, rather than creating member functions like equals().

  • When overloading operators, ensure their meaning is obvious, unsurprising and consistent with corresponding built-in operators. For example, use | as a bitwise- or logical-or, not as a shell-style pipe.

Variables

  • Do not declare global variables of class types.

  • Declare each variable on a separate line.

  • Prefer declaring a variable when it is needed i.e. give each variable the most narrow scope necessary.

  • Prefer initialisation at declaration.

Functions

  • Define parameters in the following order: inputs then outputs.

  • Use const references for input.

  • Use non-const references for output.

  • Prefer small functions; agregate multiple smaller (reusable) functions to implement higher functionality.

  • When using function overloading, avoid ambiguity - ensure the outcome is obvious.

Namespaces

  • Put the left curly brace on the same line as the namespace keyword.

  • Do not indent declarations or definitions inside namespaces.

  • Add a comment after the right curly brace at the end, repeating the namespace name.

  • Do not use using-directives in header files.

  • Do not rely on using-directives when defining classes and functions, instead define it in a properly named declarative region.

  • Do not rely on using-directives when accessing global functions.