Whenever a class declaration uses another class only as pointers, does it make sense to use a class forward declaration instead of including the headerfile in order to pre-emptively avoid problems with circular dependencies? so, instead of having:
//file C.h
#include "A.h"
#include "B.h"
class C{
A* a;
B b;
...
};
do this instead:
//file C.h
#include "B.h"
class A;
class C{
A* a;
B b;
...
};
//file C.cpp
#include "C.h"
#include "A.h"
...
Is there any reason why not to do this wherever possible?
Convenience.
If you know ahead of phase that any user of this header file will necessarily need to also include the definition of
A
to do anything (or perhaps most of the times). Then it is convenient to just include it once and for all.This is a rather touchy subject, as a too liberal use of this rule of thumbs will yield a nigh uncompilable code. Note that Boost approaches the problem differently by providing specific "convenience" headers which bundles a couple of close functionalities together.
No, explicit forward declarations should not be considered as a general guideline. Forward declarations are essentially copy and pasted, or misspelled code, which in case you find a bug in it, need to fixed everywhere the forward declarations are used. This can be error-prone.
To avoid mismatches between the "forward" declarations and its definitions, put declarations in a header file and include that header file in both the defining and the declaration-using source files.
In this special case, however, where only an opaque class is forward declared, this forward declaration may be okay to use, but in general, to "use forward declarations instead of includes whenever possible", like the title of this thread says, can be quite risky.
Here are some examples of "invisible risks" concerning forward declarations (invisible risks = declaration mismatches that are not detected by the compiler or linker):
Explicit forward declarations of symbols representing data may be unsafe, because such forward declarations might require correct knowledge of the footprint (size) of the data type.
Explicit forward declarations of symbols representing functions may also be unsafe, like the parameter types and the number of parameters.
The example below illustrates this, e.g., two dangerous forward declarations of data as well as of a function:
File a.c:
File b.c:
Compiling the program with g++ 4.7.1:
Note: Invisible danger, since g++ gives no compiler or linker errors/warnings
Note: Omitting
extern "C"
leads to a linking error forfunction()
due to the c++ name mangling.Running the program:
Yes - Performance. Class objects are stored with their data members together in memory. When you use pointers, the memory to the actual object pointed to is stored elsewhere on the heap, usually far away. This means accessing that object will cause a cache miss and reload. This can make a big difference in situations where performance is crucial.
On my PC the Faster() function runs approx 2000x faster than the Slower() function:
In parts of applications which are performance-critical or when working on hardware which is especially prone to cache coherence problems, data layout and usage can make a huge difference.
This is a good presentation on the subject and other performance factors: http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf