Skip to main content

C++ Style and Documentation

This section introduces a style guide for consistently phrasing and documenting C++ code. Consistency is key to making a codebase readable. You don't want the code to look like it was written by a 100 different people.

If you don't know any C++, you shouldn't read this section very carefully yet. We use this style in our C++ code examples. However, be aware that part of professionally developing code is being consistent.

We use the Google C++ Style Guide. We won't repeat every single rule, but we'll give you the highlights to get started. Make sure to read through their style document thoroughly.

General Style Rules

Function Names

Function names should be camel case.

void MyFunction() {
}

Function Variable Names

Function variable names should be snake case:

void MyFunction() {
int my_var;
}

Class Names

Class names should be camel case.

class Hello;

Method Names

Method names should be camel case

class Hello {
public:
void MyFunction() {
}
}

Class Variable Names

Class variable names should be snake case and be appended with a trailing "_". The underscore makes it so that we know this is a variable of the class, and not just a typical variable stored on the stack.

class Hello {
int my_var_;
};

Namespaces

Generally, classes should be encapsulated in a namespace. This avoids accidental conflicts across packages.

Namespaces are snake case. Namespaces must also be terminated using a comment which states the name of the namespace.

namespace my_namespace {

} // namespace my_namespace

Enumerations

Enumerations should be camel case. Enumeration entries should begin with a lowercase k.

enum class MyFruitEnum {
kApple,
kOrange
kDragonFruit
};

Macros

Macros should be snake case and all caps. Macros should be used sparingly since they are much harder to debug. The most common use of macros is for defining constants.

#define MY_MACRO 25

Macro function parameters should be snake case and all caps as well.

#define MY_MACRO(A, B)

Conditionals & Loops

Whenever making a conditional, ensure there is a single space between the keyword and the parenthesis.

// This is BAD
if(true) {
std::cout << "hello" << std::endl;
}

// This is GOOD
if (true) {
std::cout << "hello1" << std::endl;
} else if (false) {
std::cout << "hello2" << std::endl;
} else {
std::cout << "hello3" << std::endl;
}

// This is GOOD
while (true) {
std::cout << "hello" << std::endl;
}

// This is GOOD
do {

} while (true);

Binary Operators

Binary operators such as =, +, -, *, /, etc. should have a space on both the left and right side.

// GOOD
int c = a + b

// BAD
int c=a+b;

Linting

To ensure that your code is consistent, you can use cpplint.py. Cpplint is a python script which can inspect codebases for stylistic errors. It can be installed as follows:

python3 -m pip install cpplint
// Copyright [year] <Copyright Owner>

#ifndef MY_HEADER_GUARD
#define MY_HEADER_GUARD

namespace myNamespace {

class MyName {
int my_var_;

void MyFunc() {
int hi;
}
};

}

#endif

This violates the rule that the namespace is missing the namespace comment. cpplint can be executed as follows to detect this error:

cd ${GRC_TUTORIAL}/cpp/04-cpp-basic-syntax
cpplint --recursive src/cpplint_test.h

Output:

src/cpplint_test.h:16:  Namespace should be terminated with "// namespace myNamespace"  [readability/namespace] [5]
Done processing src/cpplint_test.h
Total errors found: 1

You can tune the set of errors cpplint checks for by creating a CPPLINT.cfg file.

Documentation

Code documentation is important to improve the readability of code and to give some guidance on how to interpret the codebase. AI models, for example, can crawl well-documented codebases to help provide examples.

The most used documentation format is called Doxygen.