Modern C++
Programming
13. Code Conventions
Part I
Federico Busato
2024-11-05
Table of Contents
1 C++ Project Organization
Project Directories
Project Files
“Common” Project Organization Notes
Alternative - “Canonical” Project Organization
2 Coding Styles and Conventions
Overview
Popular Coding Styles
1/76
Table of Contents
3 Header Files and #include
#include Guard
#include Syntax
Order of #include
Common Header/Source Filename Conventions
4 Preprocessing
Macro
Preprocessing Statements
2/76
Table of Contents
5 Variables
static Global Variables
Conversions
6 Enumerators
7 Arithmetic Types
Signed vs. Unsigned Integral Types
Integral Types Conversion
Integral Types: Size and Other Issues
Floating-Point Types
3/76
Table of Contents
8 Functions
Functions Parameters
Functions Arguments
Function Return Values
Function Specifiers
Lambda Expressions
4/76
Table of Contents
9 Structs and Classes
struct vs. class
Initialization
Braced Initializer Lists
Special Member Functions
=default, =delete
Other Issues
Inheritance
Style
5/76
C++ Project
Organization
“Common” Project Organization
6/76
Project Directories 1/2
Fundamental directories
include Project public header files
src Project source/implementation files and private headers
test (or tests) Source files for testing the project
Empty directories
bin Output executables
build All intermediate files
doc (or docs) Project documentation
7/76
Project Directories 2/2
Optional directories
submodules Project submodules
third party (less often deps/external/extern) dependencies or external
libraries
data (or extras) Files used by the executables or for testing
examples Source files for showing project features
utils (or tools, or script) Scripts and utilities related to the project
cmake CMake submodules (.cmake)
8/76
Project Files
LICENSE Describes how this project can be used and distributed
README.md General information about the project in Markdown format *
CMakeLists.txt Describes how to compile the project
Doxyfile Configuration file used by doxygen to generate the documentation (see
next lecture)
others .gitignore, .clang-format, .clang-tidy, etc.
* Markdown is a language with a syntax corresponding to a subset of HTML tags
github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet
9/76
Readme and License
README.md
README template:
- Embedded Artistry README Template
- Your Project is Great, So Let’s Make Your README Great Too
LICENSE
Choose an open source license:
choosealicense.com
License guidelines:
Why your academic code needs a software license
10/76
File extensions
Common C++ file extensions:
header .h .hh .hpp .hxx
header implementation .i.h .i.hpp -inl.h .inl.hpp
(1) separate implementation from interface for inline functions and templates
(2) keep implementation “inline” in the header file
source/implementation .c .cc .cpp .cxx
11/76
“Common” Project Organization Notes
Public header(s) in include/
source files, private headers, header implementations in src/ directory
The main file (if present) should be placed in src/ and called main.cpp
Code tests, unit and functional tests can be placed in test/ .
Alternatively, unit tests can appear in the same directory of the component
under test with the same filename and include .test suffix, e.g.
my file.test.cpp
12/76
“Common” Project Organization Example
<project name>
include/
public header.hpp
src/
private header.hpp
templ class.hpp
templ class.i.hpp
(template/inline functions)
templ class.cpp
(specialization)
subdir/
my file.cpp
README.md
CMakeLists.txt
Doxyfile
LICENSE
build/ (empty)
bin/ (empty)
doc/ (empty)
test/
my test.hpp
my test.cpp
...
13/76
“Common” Project Organization - Improvements
The “common” project organization can be
improved by adding the name of the project
as subdirectory of include/
Some projects often entirely avoid the
include/ directory
This is particularly useful when the project
is used as submodule (part of a larger
project) or imported as an external library
The includes now look like:
# include <my_project/public_header.hpp>
<project name>
include/
<project name>/
public header.hpp
src/
private file.cpp
14/76
Alternative - “Canonical” Project Organization 1/2
Header and source files (or module interface and implementation files) are next
to each other (no include/ and src/ split)
Headers are included with <> and contain the project directory prefix, for
example, <hello/hello.hpp> (no need of "" syntax)
Header and source file extensions are .hpp / .cpp ( .mpp for module
interfaces). No special characters other than
and - in file names with . only
used for extensions
A source file that implements a module’s unit tests should be placed next to that
module’s files and be called with the module’s name plus the .test second-level
extension
A project’s functional/integration tests should go into the test/ subdirectory
15/76
Alternative - “Canonical” Project Organization 2/2
<project name> (v1)
<project name>/
public header.hpp
private header.hpp
my file.cpp
my file.mpp
my file.test.cpp
test/
my functional test.cpp
build/
doc/
...
<project name> (v2)
<project name>/
public header.hpp
private/
private header.hpp
my internal file.cpp
my internal file.test.cpp
test/
my functional test.cpp
build/
doc/
...
16/76
References
Kick-start your C++! A template for modern C++ projects
The Pitchfork Layout
Canonical Project Structure
17/76
Coding Styles and
Conventions
Overview
“One thing people should remember is
there is what you can do in a language and
what you should do”
Bjarne Stroustrup
18/76
Overview
Most important rule:
BE CONSISTENT!!
“The best code explains itself
Google
19/76
Overview
“80% of the lifetime cost of a piece of
software goes to maintenance”
Unreal Engine
20/76
Code Quality
“The worst thing that can happen to a code base is size”
Steve Yegge
21/76
Bad Code
How my code looks like for other people?
abstrusegoose.com/432
22/76
Coding Styles Overview
Coding styles are common guidelines to improve the readability, maintainability,
prevent common errors, and make the code more uniform
A consistent code base helps developers better understand code organization,
focus on program logic, and reduce the time spent interpreting other engineers’
intentions
Personal Comment: Don’t start a project that involves multiple engineers without establishing clear
guidelines that all engineers agree to. This is essential to avoid costly refactoring, personal style
discussions, and conflicts later on
This section, including the review of all coding styles, has been updated on October 2024
23/76
Popular Coding Styles 1/3
LLVM Coding Standards. llvm.org/docs/CodingStandards.html
Google C++ Style Guide.
google.github.io/styleguide/cppguide.html
Webkit Coding Style. webkit.org/code-style-guidelines
Mozilla Coding Style. firefox-source-docs.mozilla.org
The Firefox code base adopts parts of the Google Coding style for C++ code (C++17, 2020),
but not all of its rules
Chromium Coding Style. chromium.googlesource.com
Chromium follows the Google C++ Style Guide with some exceptions
24/76
Popular Coding Styles 2/3
Unreal Engine - Coding Standard
docs.unrealengine.com/en-us/Programming
µOS++ (derived from MISRA 2018 and JSV)
micro-os-plus.github.io/develop/coding-style
micro-os-plus.github.io/develop/naming-conventions
More educational-oriented guidelines
C++ Core Guidelines
isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
25/76
Popular Coding Styles 3/3
Secure Coding
High Integrity C++ Coding Standard. www.perforce.com/resources
CERT C++ Secure Coding. wiki.sei.cmu.edu
Critical system coding standards
MISRA C++17, 2023. www.misra.org.uk
Autosar C++14, 2019 (based on MISRA:2008). www.autosar.org
Joint Strike Fighter Air Vehicle (JSV) C++, 2005. JSF-AV-rule
26/76
Static Analysis Tools
clang-tidy
clang.llvm.org/extra/clang-tidy/checks/list.html
PVS-Studio
pvs-studio.com/en/docs/warnings
SonarSource
rules.sonarsource.com/cpp/
cpp-checks
sourceforge.net/p/cppcheck/wiki/ListOfChecks/
Note: each tool also provides the list of checks that are evaluated
27/76
Legend
Important!
Highlight potential code issues such as bugs, inefficiency, or important
readability problems. Should not be ignored
Useful
It is not fundamental, but it emphasizes good practices and can help to prevent
bugs. Should be followed if possible
Minor / Obvious
Style choice, not very common issue, or hard to enforce
28/76
Header Files and
#include
Header Files 1/2
Every include must be self-contained
- include every header you need directly
- do not rely on recursive #include
- the project must compile with any include order
........
LLVM,
..........
Google,
.........
Unreal,
......
µOS,
............
CoreCpp
Include as less as possible, especially in header files
- do not include unneeded headers
- minimize dependencies
- minimize code in headers (e.g. use forward declarations)
........
LLVM,
..........
Google,
.............
Chromium,
..........
Unreal,
.....
Hic,
......
µOS,
...........
Mozilla,
...............
Clang-Tidy,
............
CoreCpp
Every source file should have an associated header file
...........
Google,
............
CoreCpp
29/76
Header Files 2/2
#include preprocessor should be placed immediately after the header comment
and include guard
........
LLVM,
......
µOS,
............
CoreCpp
Use C++ headers instead of C headers. C++ headers define additional
functions and their symbols are in the std namespace
.....
Hic
<cassert> instead of <assert.h>
<cmath> instead of <math.h>, etc.
30/76
#include Guard
Always use an include guard
........
LLVM,
..........
Google,
.............
Chromium,
..........
Unreal,
............
CoreCpp
macro include guard vs. #pragma once
- Use macro include guard if portability is a very strong requirement
........
LLVM,
..........
Google,
.............
Chromium,
............
CoreCpp,
...........
Mozilla,
.....
Hic
- #pragma once otherwise
..........
Webkit,
..........
Unreal
Ensure a unique name for the include guard, e.g. project name + path
...........
Googleq
31/76
#include Syntax
"" syntax
Should be absolute paths from the project include root
..........
Google,
...........
Mozilla,
.....
Hic
e.g. #include "directory1/header.hpp"
<> syntax
Any external code
..........
Webkit
Only where strictly required
..........
Google,
....
Hic,
...........
Mozilla,
............
CoreCpp
C/C++ standard library headers #include <iostream>
POSIX/Linux/Windows system headers (e.g. <unistd.h> and <windows.h>
32/76
Order of #include
........
LLVM,
..........
Webkit,
...........
Mozilla,
............
CoreCpp
(1) Main module/interface header, if exists (it is only one)
space
(2) Current project includes
space
(3) Third party includes
space
(4) System includes
Motivation: System/third party includes are self-contained, local includes might not
..........
Google: (4) (3) (2)
Note: headers within each section are lexicographic ordered
..........
Google,
..........
Webkit
33/76
#include - Other Issues
Report at least one function used for each include. It helps to identify unused
headers
<iostream> // std::cout, std::cin
Forward declarations vs. #includes
Prefer forward declaration: reduce compile time, less dependency
..............
Chromium
Prefer #include : safer
..........
Google
34/76
Common Header/Source Filename Conventions
.h .c .cc
...........
Google,
......
µOS(.h)
.hh .cc (rare)
.hpp .cpp
.....
µOS(.cpp)
.hxx .cxx (rare)
35/76
Example
// [ LICENSE ]
# ifndef PROJECT_A_MY_HEADER
# define PROJECT_A_MY_HEADER
# include "my_class.hpp" // MyClass
[ blank line ]
# include "my_dir/my_headerA.hpp" // npA::ClassA, npB::f2()
# include "my_dir/my_headerB.hpp" // np::g()
[ blank line ]
# include <cmath> // std::fabs()
# include <iostream> // std::cout
# include <vector> // std::vector
// ..
# endif // PROJECT_A_MY_HEADER
36/76
Preprocessing
Macro 1/3
Avoid defining macros, especially in headers
..........
Google
- Do not use macro for enumerators, constants, and functions
.....
µOS,
............
CoreCpp
1
,
............
CoreCpp
2
Always put macros after #include statements
.....
µOS
Macros should be unique names, e.g. use a prefix for all macros related to a
project MYPROJECT MACRO
..........
Google,
..........
Unreal,
............
CoreCpp
#undef macros wherever possible
..........
Google
- Even in the source files if unity build is used (merging multiple source files to
improve compile time)
37/76
Macro 2/3
Always use curly brackets for multi-line macro
................
Clang-Tidy
# define INCREMENT_TWO(x, y) (x)++; (y)++
if (do_increment)
INCREMENT_TWO(a, b); // (b)++ will be executed unconditionally
//---------------------------------------------------------------
# define INCREMENT_TWOO(x, y) \
{ \
(x)++; \
(y)++; \
}
Macro shall not have side effect
................
Clang-Tidy
# define MIN(X, Y) (X < Y ? X : Y) // MIN(i++) -> increased twice
38/76
Macro 3/3
In the definition of a function-like macro, each instance of a parameter shall be
enclosed in parentheses to prevent unexpected expressions
......
µOS,
................
Clang-Tidy
# define ADD(x, y) ((x) + (y))
Prefer checking macro values. It prevents mistakes deriving from missing
headers
# define MACRO 1 // defined in another header
//------------------------------------------
# if MACRO // instead of #if defined(MACRO)
Put macros outside namespaces as they don’t have a scope
39/76
Preprocessing Statements 1/2
Close #endif with a comment with the respective condition of the first #if
# if defined(MACRO)
...
# endif // defined(MACRO)
The hash mark that starts a preprocessor directive should always be at the
beginning of the line
..........
Google
# if defined(MACRO)
# define MACRO2
# endif
40/76
Preprocessing Statements 2/2
Avoid conditional #include when possible
...........
Mozilla,
.............
Chromium
Prefer #if defined(MACRO) instead of #ifdef MACRO
Improve readability, help grep-like utils, and it is uniform with multiple conditions
# if defined(MACRO1) && defined(MACRO2)
Place the \ rightmost for multi-line preprocessing statements
# define MACRO2 \
macro_def...
41/76
Variables
Variables 1/2
Always initialize variables in the declaration
..........
Google,
............
CoreCpp,
.....
Hic,
.....
µOS,
............
SEI Cert,
................
Clang-Tidy
Place variables in the narrowest scope possible. Declare variables close to the
first use
..........
Google,
............
CoreCpp
1
,
............
CoreCpp
2
,
............
CoreCpp
3
It is allowed to declare multiple variables in the same line for improving the
readability, expect for pointer or reference
..........
Google
(only one declaration per line)
............
CoreCpp
42/76
Variables 2/2
Use assignment syntax = when performing “simple” initialization, {} otherwise
..............
Chromium,
............
CoreCpp
Initialize variables with = , constructors with {}
...........
Mozilla
Variables with narrow scope need by if , while , for statements should
normally be declared within those statements if (int* ptr = f())
..........
Google
Precede boolean values with words like is and did
..........
Webkit,
.............
Chromium
Use \0 to indicate the null character
..........
Google
char n = '\0';
43/76
static Global Variables
Avoid static global variables unless they are trivially destructible
..........
Google
e.g. std::string str = is not trivially destructible
- static local variables with dynamic initialization are allowed
Avoid static global variables unless they are trivially constructible and
destructible
........
LLVM
Avoid non- const static global variables
....
Hic,
...........
Mozilla,
............
CoreCpp
Constant initialization of static global variables should be marked with
constexpr or constinit
..........
Google,
................
Clang-Tidy
static global variables should only be initialized by constant expressions (e.g.
constexpr functions/lambdas)
..........
Google,
................
Clang-Tidy
44/76
Conversions
Use static cast instead of old-style cast
..........
Google
Use const cast to remove the const qualifier only for pointers and references
..........
Google
Avoid const cast to remove const , except when implementing non- const
getters in terms of const getters
.............
Chromium
Use reinterpret cast to do unsafe conversions between pointer types, and
from/to integer types
..........
Google
Use std::bit cast to interpret the raw bits of a value using a different type of
the same size
..........
Google
45/76
Enumerators
Enumerators
Prefer enumerators over macros
............
CoreCpp
Prefer enum class over plain enum
.........
Unreal,
......
µOS,
............
CoreCpp
Specify the underlying type and enumerator values only when necessary
............
CoreCpp
1
,
............
CoreCpp
2
enum class MyEnum : int16_t { Abc = 1, Def = 2 }; // bad
Do not cast an expression to an enumeration type
Color c = static cast<Color>(3)
.....
Hic
Don’t use ALL CAPS for enumerators
............
CoreCpp
46/76
Arithmetic Types
Signed vs. Unsigned Integral Types
Don’t mix signed and unsigned arithmetic
............
CoreCpp,
.....
µOS
Prefer signed integers whatever possible
..........
Google,
......
µOS,
............
CoreCpp,
Use unsigned integer only for bitwise operations
..........
Google,
......
µOS,
............
CoreCpp
Do not shift signed operands
.....
Hic,
......
µOS,
................
Clang-Tidy
size t vs. int64 t
- Use int64 t instead of size t for object counts and loop indices
..........
Google
- Use size t for object and allocation sizes, object counts, array and pointer offsets,
vector indices, and so on (to avoid overflow undefined behavior)
.............
Chromium
Do not apply unary minus to operands of unsigned type, e.g. -1u
.....
Hic
47/76
Integral Types Conversion
Avoid silent narrowing conversions, e.g, int i += 0.1;
................
Clang-Tidy
Use brace initialization to convert/define constant arithmetic types
(narrowing) e.g. int64 t{MyConstant}
..........
Google
Use intptr t to convert raw pointers to integers
..........
Google
Be aware of implicit cast to int
48/76
Integral Types: Size and Other Issues
Size:
Except int , use fixed-width integer type (e.g. int64 t , int8 t , etc.)
.............
Chromium,
..........
Unreal,
..........
Google,
.....
Hic,
......
µOS,
................
Clang-Tidy
Prefer 32/64-bit signed integers over smaller data types
..........
Google
64-bit integers add no/little overhead on 64-bit platforms
Other issues:
Avoid redundant type, e.g. unsigned int , signed int
..........
Webkit
49/76
Floating-Point Types 1/2
Floating point numbers shall not be converted to integers except through
use of standard library functions std::floor , std::ceil
......
µOS,
.....
Hic
double d = ...;
int i = d; // BAD, prefer std::floor(d)
Don’t convert an expression of wider floating-point type to a narrower
floating-point type
.....
Hic
float f1 = 1.0; // Bad
float f2 = 1.0F; // Ok
50/76
Floating-Point Types 2/2
Do not directly compare floating point == , < , etc.
.....
Hic,
.....
µOS
Floating-point literals should always have a radix point, with digits on both sides,
even if they use exponential notation 2.0f
..........
Google,
..........
Webkit (opposite)
51/76
Functions
Functions 1/2
A function should perform a single logical operation to promote simple
understanding, testing, and reuse
............
CoreCpp
Split up large functions ( 40) into logical sub-functions for improving
readability and compile time
..........
Unreal,
..........
Google,
............
CoreCpp,
................
Clang-Tidy
Prefer pure functions, namely functions that always returns the same result
given the same input arguments (no external dependencies) and does not modify
any state or have side effects outside of returning a value
............
CoreCpp
52/76
Functions 2/2
Limit overloaded functions. Prefer default arguments
...........
Google,
............
CoreCpp
(don’t use default arguments)
.....
Hic
Overload a function when there are no semantic differences between
variants
..........
Google
53/76
Functions Parameters 1/4
Don’t declare functions with an excessive number of parameters. Use a
wrapper structure instead
.....
Hic,
...........
CoreCpp,
..........
Unreal,
.....
µOS
Specify all input-only parameters before any output parameters
..........
Google
Avoid adjacent parameters of the same type easy to swap by mistake
............
CoreCpp
54/76
Functions Parameters - Input/Output 2/4
Pass-by- const -pointer or reference for input parameters are not intended to
be modified by the function
...........
Google,
..........
Unreal
Use std::optional to represent optional by-value input parameters
..........
Google
Pass-by-reference for input/output parameters
............
CoreCpp
Pass-by-reference for output parameters, except rare cases where it is optional in
which case it should be passed-by-pointer
..........
Google
55/76
Functions Parameters - By-Value, By-Rvalue 3/4
Prefer pass-by-value for small and trivially copyable types
............
CoreCpp,
.....
Hic
Don’t pass-by- const -value, especially in the declaration (same signature of
pass-by-value)
..........
Google
(opposite) Autosar
Don’t use rvalue references && except for move constructors and move
assignment operators
..........
Google
56/76
Functions Parameters 4/4
Boolean parameters should be avoided
..........
Unreal
Prefer enum to bool on function parameters
..........
Webkit,
.............
Chromium
Parameter names should be the same for declaration and definition
................
Clang-Tidy,
.....
Hic
All parameters should be aligned if they do not fit in a single line (especially in the
declaration)
void f(int a,
const int* b);
57/76
Functions Arguments
Consider introducing variables to describe the meaning of arguments
..........
Google
f(true); // BAD
bool enable_checks = true; // GOOD
f(enable_checks);
Use argument comment to describe “magic number” arguments
...............
Clang-Tidy,
..........
Google
void f(bool enable_checks);
f(/*enable_checks=*/ true);
All arguments should be aligned to the first one if they do not fit in a single line
..........
Google
my_function(my var1, my_var2,
my_var3);
58/76
Function Return Values 1/2
Prefer to return values rather than output parameters
...........
Google,
............
CoreCpp
Prefer to return by-value
..........
Google
Prefer to return a struct /structure binding to return multiple output values
............
CoreCpp
Don’t return const values
............
CoreCpp
Use trailing return types only where using the ordinary syntax is impractical or
much less readable
..........
Google,
..........
Webkit
int foo(int x) instead of auto foo(int x) -> int
59/76
Function Return Values 2/2
Transfer ownership with smart pointers. Never return pointers for new objects.
Use std::unique ptr instead
...........
Google,
..............
Chromium,
............
CoreCpp
int* f() { return new int[10]; } // wrong!!
std::unique_ptr<int> f() { return new int[10]; } // correct
void FooConsumer(std::unique_ptr<Foo> ptr); // correct
Never return reference/pointer for local objects. Return a pointer only to
indicate a position
............
CoreCpp
1
,
............
CoreCpp
2
,
..........
Google,
............
SEI Cert
60/76
Function Specifiers
If a function might have to be evaluated at compile time, declare it constexpr
............
CoreCpp
1
,
............
CoreCpp
2
Do not separate declaration and definition for template and inline functions
..........
Google
Use inline only for small functions (e.g. 10 lines, no loops or switch
statements)
..........
Google,
.....
Hic,
............
CoreCpp
Do not use inline when declaring a function (only in the definition)
Do not use inline when defining a function in a class definition
........
LLVM
Use noexcept when it is useful and correct
..........
Google
61/76
Lambda Expressions
Prefer explicit captures if the lambda may escape the current scope
..........
Google
Use default capture by reference ( [&] ) only when the lifetime of the lambda is
obviously shorter than any potential captures
...........
Google,
............
CoreCpp
Do not capture variables implicitly in a lambda, e.g. [&]{body}
.....
Hic
Omit parentheses for a C++ lambda whenever possible
[this] { return m member; }
..........
Webkit
(opposite)
.....
Hic
int a[] { ++i }; // Not a lambda
[] { ++i; }; // A lambda
62/76
Structs and Classes
struct vs. class
Use struct only for passive objects that carry data; everything else is
class
...........
Google,
............
CoreCpp
Use class rather than struct if any member is non- public
............
CoreCpp
Prefer struct instead of pair or tuple
..........
Google
63/76
Initialization
Objects are fully initialized by constructor calls and all resources acquired
must be released by the class’s destructor
..........
Google,
............
CoreCpp
1
............
CoreCpp
2
,
.....
Hic,
................
Clang-Tidy
Prefer in-class initializers to member initializers
.............
Chromium,
............
CoreCpp
1
,
...........
CoreCpp
2
................
Clang-Tidy
Initialize member variables in the order of member declaration
............
CoreCpp,
.....
Hic
Prefer initialization to assignment in constructors
............
CoreCpp
struct A {
int _x;
A(int x) { x = _x; } // bad
64/76
Braced Initializer Lists
Initialize variables with = , constructors with {}
...........
Mozilla
Prefer braced initializer lists {} for constructors to clearly distinguish from
function calls, avoid implicit narrowing conversion, and avoid the most vexing
parse problem
............
CoreCpp
1
,
............
CoreCpp
2
,
............
CoreCpp
3
void f(float x) {
int v(int(x)); // function declaration
int v{int(x)}; // variable
}
Do not use braced initializer lists {} for constructors (at least for containers, e.g.
std::vector ). It can be confused with std::initializer list
........
LLVM
65/76
Special Member Functions
Use delegating constructors to represent common actions for all
constructors of a class
............
CoreCpp,
.....
Hic
Mark destructor and move constructor/assignment noexcept
............
CoreCpp
1
,
............
CoreCpp
2
,
.....
Hic
1
,
.....
Hic
2
,
............
SEI Cert,
................
Clang-Tidy
Avoid implicit conversions. Use the explicit keyword for conversion
operators and constructors, especially single argument constructors
..........
Google,
............
CoreCpp
1
,
............
CoreCpp
2
,
.....
Hic,
......
µOS,
................
Clang-Tidy
66/76
=default, =delete
Indicate if a non-trivial class is copyable, move-only, or neither copyable
nor movable by using = default / = delete for constructors and assignment
operators if not directly implemented
..........
Google,
...........
Mozilla,
..............
Chromium,
............
CoreCpp
Prefer = default constructors over user-defined / implicit default
constructors
..........
Mozilla,
.............
Chromium,
............
CoreCpp,
.....
Hic
Use = delete for mark deleted functions
............
CoreCpp,
.....
Hic
67/76
Structs and Classes - Other Issues 1/2
Don’t return pointers or references to non- const objects from const
methods
.............
Chromium
Use const functions wherever possible
..........
Google,
.............
Chromium,
......
µOS,
................
Clang-Tidy
Make a function a member only if it needs direct access to the representation of a
class. Use a static function or a free-function otherwise
............
CoreCpp
Don’t define a class or enum and declare a variable of its type in the same
statement, e.g. struct Data /*...*/ data;
............
CoreCpp
68/76
Structs and Classes - Other Issues 2/2
Do not overload operators with special semantics && , ˆ && , || , , , & ,
operator"" (user-defined literals)
..........
Google,
.....
Hic,
.....
µOS
Prefer to define non-modifying binary operators as non-member functions
e.g. operator==
..........
Google,
.....
Hic
Place free-functions that interact with a class in the same namespace, e.g.
operator==
............
CoreCpp
Declare data members private , unless they are constants. This simplifies
reasoning about invariants
..........
Google,
.....
Hic
69/76
Inheritance 1/2
Avoid virtual method calls in constructors
..........
Google,
............
CoreCpp,
............
SEI Cert
Default arguments are allowed only on non-virtual functions
..........
Google,
............
CoreCpp,
.....
Hic,
................
Clang-Tidy
A class with a virtual function should have a virtual or protected destructor
(e.g. interfaces and abstract classes)
............
CoreCpp
Always use
override/final function member keywords
..........
Google,
..........
Webkit,
...........
Mozilla,
..........
Unreal,
....
Hic,
................
Clang-Tidy,
............
CoreCpp
Does not use virtual with final/override (implicit)
70/76
Inheritance 2/2
Provide a virtual method anchor ( .cpp implementation) for classes in
headers
........
LLVM
Multiple implementation inheritance is discouraged
..........
Google,
..............
Chromium,
.....
Hic,
................
Clang-Tidy
Prefer composition to inheritance
..........
Google
Inheritance should be public
..........
Google
A polymorphic class should suppress public copy/move semantics
............
CoreCpp
71/76
Structs and Classes - Style 1/5
Declare class data members in special way
- It helps to keep track of class variables and local function variables
- The first character is helpful in filtering through the list of available variables
Examples:
- Trailing underscore (e.g. member var )
..........
Google,
......
µOS,
.............
Chromium
- Leading underscore (e.g. member var ) .NET
- Public members (e.g. m member var , mVar )
..........
Webkit,
...........
Mozilla
- Static members (e.g. s static var , sVar )
..........
Webkit,
...........
Mozilla
Personal Comment: Prefer member var as I read left-to-right and is less invasive
Class members are indented
..........
Google
72/76
Structs and Classes - Style 2/5
Class inheritance declarations order:
public , protected , private
..........
Google,
......
µOS,
............
CoreCpp
Declarations order
..........
Google
(a) Types and type aliases
(b) (Optionally, for structs only) non-static data members
(c) Static constants
(d) Factory functions
(e) Constructors and assignment operators
(f) Destructor
(g) All other functions
(h) All other data members
73/76
Structs and Classes - Style 3/5
struct A { // passive data structure
int x;
float y;
};
class B {
public:
B();
void public_function();
protected:
int _a; // in general, it is not public in derived classes
void _protected_function(); // "protected_function()" is not wrong
// it may be public in derived classes
private:
int _x;
float _y;
void _private_function();
};
74/76
Structs and Classes - Style 4/5
In the constructor, each member of the initializer list should be indented on a
separate line, e.g.
..........
Google,
..........
Webkit
A::A(int x1, int y1) :
x{x1}, // double indentation
y{y1} {
body
}
A::A(int x1, int y1) :
: x{x1},
y{y1} {
body
}
75/76
Structs and Classes - Style 5/5
If possible, avoid this-> keyword
Prefer empty() method over size() to check if a container has no items
...........
Mozilla
Do not use get for observer methods ( const ) without parameters, e.g.
get size() size()
..........
Webkit
Precede getters that return values via out-arguments with the word get
.............
Chromium
Precede setters with the word set . Use bare words for getters
..........
Webkit,
.............
Chromium
76/76