Should one use forward declarations instead of includes wherever possible?
The forward-declaration method is almost always better. (I can't think of a situation where including a file where you can use a forward declaration is better, but I'm not gonna say it's always better just in case).
There are no downsides to forward-declaring classes, but I can think of some downsides for including headers unnecessarily:
longer compilation time, since all translation units including
C.h
will also includeA.h
, although they might not need it.possibly including other headers you don't need indirectly
polluting the translation unit with symbols you don't need
you might need to recompile source files that include that header if it changes (@PeterWood)
Yes, using forward declarations is always better.
Some of the advantages they provide are:
- Reduced compilation time.
- No namespace pollute.
- (In some cases)may reduce the size of your generated binaries.
- Recompilation time can be significantly reduced.
- Avoiding potential clash of preprocessor names.
- Implementing PIMPL Idiom thus providing a means of hiding implementation from the interface.
However, Forward declaring a class makes that particular class an Incomplete type and that severely, restricts what operations you can perform on the Incomplete type.
You cannot perform any operations which would need the compiler to know the layout of the class.
With Incomplete type you can:
- Declare a member to be a pointer or a reference to the incomplete type.
- Declare functions or methods which accepts/return incomplete types.
- Define functions or methods which accepts/return pointers/references to the incomplete type (but without using its members).
With Incomplete type you cannot:
- Use it as a base class.
- Use it to declare a member.
- Define functions or methods using this type.
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.
One case in which you don't want to have forward declarations is when they are themselves tricky. This can happen if some of your classes are templated, like in the following example:
// Forward declarations
template <typename A> class Frobnicator;
template <typename A, typename B, typename C = Frobnicator<A> > class Gibberer;
// Alternative: more clear to the reader; more stable code
#include "Gibberer.h"
// Declare a function that does something with a pointer
int do_stuff(Gibberer<int, float>*);
Forward-declarations are the same as code duplication: if the code tends to change a lot, you have to change it in 2 places or more each time, and that is no good.
Fun fact, in its C++ styleguide, Google recommands using #include
everywhere but to avoid circular dependencies.