There are some strict conventions to obey wrt the files and their contents.
The *.hh should contain only declarations, i.e., prototypes,
extern
for variables etc. Inlined short methods are accepted when there are few of them, otherwise, create an *.hxx file, and include it at the end of this header file. The documentation should be here too.There is no good reason for huge objects to be defined here.
As much as possible, avoid including useless headers (GotW007, GotW034):
- when detailed knowledge of a class is not needed, instead of
#include "foo.hh"write
// Fwd decl. class Foo;- if you need output stream, then include ostream, not iostream. Actually, if you merely need to declare the existence of streams, you might want to include iosfwd.
If there are definitions that should be loaded in different places (definitions of templates, inline functions etc.), then declare and document them in the *.hh file, and implement them in the *.hxx file. Note that this file should first include its corresponding *.hh file, the latter including itself this file. It is indeed surprising, but the header guards make this work properly.
Big objects should be defined in the *.cc file corresponding to the declaration/documentation file *.hh.
There should be only pure functions in the interface of a module. That means that the functions in these files should not depend upon globals, nor have side effects of global objects. Of course no global variable can be defined here either.
Dependencies can be a major problem during big project developments. It is not acceptable to “recompile the world” when a single file changes. To fight this problem, you are encouraged to use fwd.hh files that contain simple forward declarations, to the used by other *.hh files. The expected benefit is manifold:
- A forward declaration is much shorter.
- Usually actual definitions rely on other classes, so other #includes etc. Forward declarations need nothing.
- While it is not uncommon to change the interface of a class, changing its name is infrequent.
Of course, usually the *.cc files need actual definitions.
Tasks, as designed currently, are the place for side effects. That's where globals such as the current ast, the current assembly program, etc., are defined and modified.