Files
| Rule 7. Chose descriptive filenames according to their content. |
This basic rule substantially simplifies the search for the declaration or implementation of a specific function or class. For example it is a good idea to use directly the name of the class declared in an include file as its filename. Furthermore you should also separate files belonging to different namespaces or modules by using different directories or prefixes. For example I always use the namespace as a prefix for my class files
graphics.point.h instead of point.h
This is a natural consequence of the usage of namespaces, because these allow the definition of two different objects with the same name as long as they live in different namespaces. This fact as to be considered when choosing the name of a file.
| Rule 8. Every include file must contain a mechanism that prevents multiple inclusions of the file. |
Usually this is done by the following construct:
// includeme.h #ifndef __INCLUDEME_H #define __INCLUDEME_H ... #endif |
Some compilers (for example Microsoft Visual C++) also provide vendor specific mechanisms like #pragma once, but I highly discourage to employ such techniques as they are not portable across compilers at all.
| Rule 9. Every file should contain at most one class. |
You should always avoid big source files, as these make finding a particular function much harder. It turned out that having one header file for declaration, one include file for inline functions and one source file for the implementation for every class is a very good thing. Even if the class is very small, this approach makes a lot of sense, especially if the files names are directly derived from the class names. This approach also enables a better team work, as it is much easier for different people working on different classes. The possibility that to developers need to change one file simultaneously is significantly smaller than it would be the case with big and complex source files.
| Exception to 9. If two classes are tight coupled, they may be declared and implemented in one file respectively. |
For example if you have a class Queue that only stores objects that are derived from a class Queueable, then it is absolutely reasonable to define both classes Queue and Queueable together in one file and to implement them together in another file.
| Rule 10. Functions and methods are always implemented in source files or inline files and never in header files. |
Implementing a function in a header file both means bad style and unnecessary time spent compilation if you change some implementation detail. Plus you will have more than one instance of a function which in turn will result in the linker complaining with warnings and errors. It is even a good idea to move the source code of inline functions into special files that are included only by sources that really need the implementation of these functions.
| Rule 11. Data definitions always take place in source files and never in header files. |
Although it would be nice to assign values to variables in the declaration of a class, this is illegal in most cases (see below for one important exception). You always have to define static variables in a source file and exactly once, or your linker will complain about multiple instances of a variable. All non static member variables have to be defined in class constructors. See the following example for details
// class.h
int g_Variable;
class A {
private:
int m_Member;
static int g_Global;
static const int g_Constant = 3; // See next exception
public:
A();
};
// class.cpp
int g_Variable = 1;
int A::g_Globale = 2;
A::A() {
m_Member = 4;
}
|
| Exception to 11. Integer variables, which are declared static const and which are used instead of #define's or enum's have to be defined in the header file. |
Modern C++ compilers allow the declaration and immediate definition of integer variables which are declared as static const. These variables are meant to replace #define's or enum's for constants. But beware that not all compilers support this feature, so it might be better to use the enum-hack instead in order to declare constants. But you should never use #define's for anything else than prevention of multiple inclusions of a file and for target specific code compilation.
Kaya Memisoglu 2005-01-06
