Skip to content

File and Module Structure

amirroth edited this page Sep 21, 2021 · 10 revisions

Distinguish C++ Files From C Files

  • C++ source file should be named .cpp or .cc NOT .c
  • C++ header files should be named .hpp or .hh NOT .h

Include Guards

Header files must contain an distinctly named include guard to avoid problems with including the same header multiple times or conflicting with other headers from other projects

#ifndef MYPROJECT_MYCLASS_HPP
#define MYPROEJCT_MYCLASS_HPP

namespace MyProject {
class MyClass {
};
}

#endif

Use "" For Including Local Files

... <> is reserved for system includes.

// Bad Idea. Requires extra -I directives to the compiler
// and goes against standards
#include <string>
#include <includes/MyHeader.hpp>

// Worse Idea
// requires potentially even more specific -I directives and 
// makes code more difficult to package and distribute
#include <string>
#include <MyHeader.hpp>


// Good Idea
// requires no extra params and notifies the user that the file
// is a local file
#include <string>
#include "MyHeader.hpp"

[SM] The reason for <path/MyHeader.hpp> is two-fold:

  • Search semantics for "MyHeader.hpp" are not fully specified in the language and thus creates a potential portability problem. Search with <> is precisely specified. This is particularly important for cross-platform projects where you may want precise override control to pick up different headers depending on the platform/compiler (for a cleaner more maintainable approach than an #ifdef mess).
  • Putting a namespace path in front of the header file name prevents header name collisions between the application and a library or 2 application namespaces.
  • These reasons are why projects like Boost use the <boost/header.hpp> style.

[JT] Having just grepped through the boost source: there is a surprising amount of inconsistency within boost. Practically speaking, I have never seen a portability issue with using "" for includes, and have seen it solve far more problems then it has created. However if we do use the <> includes as you suggest, we need to be consistent and use fully scoped paths, like boost does, (real world example) boost/log/expressions/predicates.hpp:#include <boost/log/expressions/predicates/channel_severity_filter.hpp>

Always Use Namespaces

There is almost never a reason to declare an identifier in the global namespaces. Instead, functions and classes should exist in an appropriately named namespaces or in a class inside of a namespace. Identifiers which are placed in the global namespace risk conflicting with identifiers from other (mostly C, which doesn't have namespaces) libraries.

Forward Declare when Possible

This:

// some header file
class MyClass;

void doSomething(const MyClass &);

instead of:

// some header file
#include "MyClass.hpp"

void doSomething(const MyClass &);

This is a proactive approach to simplify compilation time and rebuilding dependencies.

Never Use using In a Header File

This causes the name space you are using to be pulled into the namespace of the header file.

Avoid using In C++ Implementation Files

This reduces the code readability.

Clone this wiki locally