C++ Coding Standards
Naming Conventions
- Use mixed case for variable names and begin variable names with a
lowercase letter.
- Use mixed case for class, function, and type names and begin such
names with an uppercase letter.
- Use only uppercase characters for named constants, macros, and
enumeration constants.
- Use multiword identifiers. In mixed case names, capitalize the first
letters of the contained words in multiword identifiers to enhance readability.
For example: maxElement,
currentFile, and so on. In single case
names, separate the words in a multiword name with underscores. For example:
BUFFER_SIZE.
- Use names that describe the roles of variables, functions, classes,
types, constants, and macros--this generally means that names should be more
than two or three characters long. For example, use
charPtr rather than
p. The exception is integer loop control
variables used to index arrays, which are traditionally
i, j, and k.
- [Optional] Use the prefix "is"
for Boolean variables and "Is" for
Boolean functions. Use the suffix Class
for class names, Type for type names,
and Ptr for pointer variables and
functions. For example, isFound is a
Boolean variable, CarClass is a class
name, NodeType is a type name, and
NodePtr is a function returning a
pointer.
These naming conventions allow program readers to recognize many
program objects at a glance. For example, DocumentClass is a class,
IsEmpty is a function returning a
Boolean value, and MEMORY_ERROR is a
constant of some kind, either a named constant, an enumeration value, or a
macro.
Formatting
- Use standard indentation conventions for block structured languages.
- Indent 3 spaces at a time.
- Place braces alone on lines indented to the same column as the
statement(s) they delimit (the Pascal model).
- Place at most one variable declaration, type definition, or statement
on a single line of code. Use the rest of the line for comments.
- Use vertical white space to separate code into segments that do parts
of a whole task carried out in a block.
- Use horizontal white space to reflect precedence in expressions.
Types
- Avoid the float and
unsigned types. Use
double and the signed types instead.
- Use the char type only for
character data.
- Declare data structures akin to traditional records as
structs; reserve the
class type for truly object-oriented
encapsulations of data and functions.
- Make type definitions for struct and enumeration types. Complex type definitions should
always be factored.
- Never default declarations.
Expressions
- Use parentheses liberally.
- Avoid expressions with side-effects.
- Avoid mixed types in expressions--cast values to the needed types.
- Simplify complex Boolean expressions by factoring, and by using
DeMorgan's Laws to drive negations inward.
- Use <= and < instead of >= and >.
- Put constants on the left in comparisons.
- Make loop termination expressions as weak as possible.
Control Structures
- Avoid the goto and
continue statements.
- Use comments to mark missing loop parameters and missing
switch break statements. Use either
comments or an empty pair of brackets to mark null loop bodies.
- Make infinite loops with the construct
while ( TRUE ).
- Always have a default case in
switch statements.
Functions and Operators
- Pass parameters by value in preference to by reference, and by
reference in preference to passing pointers.
- Make parameters constant if possible.
- Avoid function overloading--default parameters help with this.
- Avoid operator overloading. If operators are defined, construct a
complete set of operators.
Classes
- In every class declaration, have sections for public, protected, and
private members, even if they are empty.
- Only declare constructor and destructor functions that do something.
- Classes whose constructors allocate space should have a copy
constructor and a destructor that frees the space.
- Make base class destructors virtual.
- Avoid static members.
Modules and Access to Program Objects
- A compilable source file is called a compile module. Form and
name compile modules in an effort to reflect program structure, with emphasis
on principles of cohesion, coupling, and information hiding. In particular,
place classes in their own compile modules.
- Associate header files with individual compile modules.
- Make the scope of declarations as local as possible (avoid non-local
and especially global variables).
- Declare functions and non-local variables not referenced outside the
compile modules in which they are defined static.
- Declare functions and non-local variables referenced outside the
compile modules in which they are defined extern in all non-defining declarations.
- Declare functions and non-local variables referenced outside the
compile modules in which they are defined neither
extern nor
static in their unique defining
declaration.
- Restrict access to class members as much as possible (prefer private
to protected members, and protected to public members).
- Avoid friend functions.
- Try to flatten and simplify inheritance hierarchies--avoid multiple
inheritance.
Use of the Preprocessor
- Avoid macros in favor of named constants or inline functions.
- Do not use the preprocessor to disguise the C language.
- Fully parenthesize macro definitions.
Comments
- Start each module with a banner comment stating the module name,
purpose, writer, and notes explaining any special features of the module. In
maintenance, record the date, programmer, purpose, and description of all
changes to the module.
- Precede each function definition with a banner comment stating the
name and purpose of the function, and notes explaining any side effects,
references to sources, explanations of algorithms, and so on.
- In long sequences of code, break the code into cohesive blocks and
precede each one with a summary of the processing carried out in the block.
- If necessary, supplement role information captured in an object's
name by a comment at the object's definition or declaration.
- Explain an object's purpose at its point of definition or
declaration.
- Note for every parameter whether it is an in, out, or
in/out parameter.
- Explain non-role-based operations when they occur.
- Document unexpected side-effects in code segment comments (like
header comments), at the point of declaration of the affected object and at the
points where the side-effect occurs.
Error Checking
- Write functions likely to generate errors so that they either handle
errors themselves, or return an error code.
- Check the return codes of functions that return error codes, and
handle or propagate any errors indicated by return codes.
- Check parameters likely to be used improperly before doing any
processing.
Target Metric Values
- Aim for function comment-to-code ratios of at least 0.8.
- Try to write functions with no more than 60 NCSL.
- Try to write compile modules with no more than 500 NCSL.
- Do not exceed a block nesting level of 7.
Return to Home Page
Copyright 1999 Christopher Fox