C++ Coding Guidelines
The following are guidelines, with explanations where needed (as
some techniques may seem unorthodox to the uninitiated) to
programming in C++. They are designed and derived from my work at
LLNL (any many were developed by my group there prior to my joining,
although I have made extensive revisions), but they should provide a
good guide or starting point for work at any organization.
General:
Comments:
- All files should start with a file comment in the style:
/*
* File.H
*
* Overview of what is in this file, why it exists and how it fits
* into "The Big Picture".
*
* Author: Your Name <yname@domain.tla>
* (Insert other authors here)
* (Note: The top author should be the current maintainer of the file.
* That is, they should be able to answer any questions regarding the
* code or content of the file.)
*
* Date: <Date of Origination>
*/
- Comment before you code. This is perhaps the best way to ensure
that you write quality code. Start with a high level summary of
what a function or method is suppose to do. Fill in some high level
details of how it does that as comments in the body. Drill down
each of those details iteratively until you think that writing code
would be easier than describing a step in any more detail. Only
then should you write any code. Doing this not only ensures that all
of your code is throughly documented, but it establishes that you
have thought through all the details of the function and hence that
your code is logically correct.
- Don't use separators (a long line of dashes, stars or the like)
in comments. They are difficult to create or maintain, and they
provide little if any additional readability (in some cases, they
may actually distract).
- Comment the end of class and function definitions, and the end of
long loop or conditional statements. This allows someone reading the
code to immediately know what a closing curly brace ('}') belongs to.
This should even be done for small classes and functions to get in
the habit and in case they should become larger in the future.
Class syntax
/**
* One-line summary of the class. This is followed by a detailed overview of
* what the class is, why it exists, how it should be used, how it fits into
* the object structure of the rest of the design, what other classes it uses,
* is tightly coupled to and anything else that seems relevant to understanding
* the purpose of this class.
*/
/* Note that the above comment started with two stars after the slash. That
* denotes that the comment provides DOC++ style comments.
* Any notes on the implementation that are only of interest to someone
* working on the class, and not just using the class, may be placed in a
* normal block comment below the DOC++ comment.
*/
/* Templates should be avoided in lieu of the use of an Abstract Base Class
* abstracting out the functionality of the classes that will be used
* by this class. Templates should only be used if this class needs to
* abstractly handle intrinsic types, or in the rare cases that it provides
* a measurable and needed performance improvement.
*/
template <class Type>
class Class_One: public Class_Parent {
public:
// Constructors
Class_One();
// Destructors
~Class_One();
// Manipulators
do_Something();
// Accessors
size();
protected:
int inheritable;
private:
int size_;
}; // end Class_One
Member Functions
- Names should start with a lowercase letter. Multiple word names
should be separated by an underscore ('_'). Successive words in
the name should start with a capitol letter. This prevents
confusion with variable names;
- Avoid the use of "get_" like "get_Size()". Instead, just use the
name like "size()".
- Avoid the use of "set_" as well. Instead, overload the member
function to allow the same function to get and set a member variable
depending on the signature (what's passed to it).
Variables
- The entire name should be in lower case.
- Multiple word variable names should be separated by an underscore
('_'). General variables should be in all lower case.
- In the event that a member function and variable name collide
(i.e. size), append an underscore ('_') to the end of the variable
name.
- Do not use single character variable names like i, j or k, unless
that name is the commonly accepted mathematical notation for a
concept such as the unit vector in the x direction. Loop control
variables can always use more descriptive names, such as index,
matrix_number or file_number. Failure to be able to provide a more
meaningful variable name denotes a failure to understand what you're
really looping through. Further, single character variable names can
easily be mistaken for numbers in many fonts (like my favourite
Fortran statement: FOR i=i to end).
- Use a more descriptive name for templated types than T, like
Stored_Type, Data or Key. While Stroustrup may only use T, his
style is not expressive of any experience he may of had in working
on or maintaining a large code.
- Declare variables where they're first used. C++ lifted this
restriction from C for a reason. When someone new looks at a piece of
code (like when an assertion fires in a part they didn't write), it
should be immediately apparent what the type of the variables in
the surrounding statements is.
Constants and macros
- Constants should be in all upper case ("CONSTANT_VARIABLE").
- Constants should be declared as const NAME = value;
instead of using #define. This allows easier compile time type
checking and easier tracking of where values came from at debug
time.
- Avoid the use of Macros. They make maintenance very difficult
as they look like functions but weren't declared that way. Further,
they may cause difficult to track compile time errors in the event
of a name collision. If you feel you must use one, define it just
before you use it and #undef it as soon as you're done. This
should make the macro's presence and purpose immediately evident
to any maintainer.
File format
- Only one class (and any associated typedefs, constants, etc.)
should be declared in each .H/.C pair.
- Files should be named for the (singular) class that they contain,
i.e. Class_Name.H/Class_Name.C .
- .C (Source) files are for definitions and functions more than one
line long.
Preprocessor and header files
Spacing
- Limit lines to 80 characters. While screens may be bigger today,
most terminals aren't by default, and most printers aren't at
all in text mode.
- Three (3) space indentation. If someone knows how to set up emacs
to make this my default, please let me
know how (I know, I just haven't had a chance to RTFM.
- Insert spaces for readability. This means that at least one
blank line should occur between function definitions.
Iterators
- Use separate iterators where ever appropriate. Do not implement
iterators inside the class they should access (this causes major
problems in multi-threaded code).
- Use consistently throughout the code.
- See the implementation of iterators in the STL for examples.
"Zow" Terry Brugger
Last modified: Sun Jan 24 22:49:59 PST 1999