For every pointer p1
of class class1
, are there any risks we should consider by using a forward declaration of class1
instead of including class1
header file?
I can see only the advantage: The header file will have less size.
For every pointer p1
of class class1
, are there any risks we should consider by using a forward declaration of class1
instead of including class1
header file?
I can see only the advantage: The header file will have less size.
Forward declarations outside the control of the provider of the class are problematic! I’m working on a code base where a lot of forward declarations are used. While things are initially great the existence of forward declarations become a legacy:
typedef
or using alias
).Assuming the forward declarations are provided via a header under the control of the class provider/implementer (e.g., the implemented providing something akin to <iosfwd>
) these problems are not relevant as there is a central place where the declarations can be changed. However, having users decide to declare entities becomes a legacy causing significant cost.
The approach to provision of declarations outlined above seems to have caused some confusion. I'll try to clarify. In my mind the unit of implementation is a component (which is based on John Lakos's notation of a component). A component defines one or more closely related classes and/or functions. The implementation of a component consists of multiple files:
<iosfwd>
is an example of such a header shared across multiple components).Users of a component which in some contexts only need to know about names in the component would include the declaration-only header. In no case would a user provide a declaration of a name in a component: all declaration of a name in a component are the responsibility of the provider/implementer of the component.
I can see only the advantage: The header file will have less size.
That's not exactly the point.
Let's assume you have a class declaration in a header file like
namespace MyNamespace {
class Baz;
}
class Foo {
public:
void bar(const MyNamespace::Baz & x);
};
and the definition in a separate translation unit as
#include "Baz.hpp"
void Foo::bar(const MyNamespace::Baz & x) {
// actually do something with Baz
}
and in contrast having everything included in the header file (and necessarily all dependent sources will be recompiled when Baz.hpp
will be changed)
#include "Baz.hpp"
class Foo {
public:
void bar(const MyNamespace::Baz & x);
};
with the declaration, the 1st version might help to compile the code a little bit faster.
Especially if you have your own headers and class declarations, and if any of these are likely to be changed, you only want to recompile your translation units in the codebase, and not every source file that includes your type dependent header.
Note that forward declarations can be only used with references and pointers. Also header inlined code which dereferences to the forwarded type members cannot be used.