I just had an interview. I was asked what is a \"forward declaration\". I was then asked if they were dangers associated with forward declarations.
I could not answer to
Forward declaration is the symptom of C++ missing modules (going to be fixed in C++17?) and using headers inclusion, if C++ had modules there were no need at all for forward declarations.
A forward declaration is not less than a "contract", by using it you actually promise that you will provide the implementation of something (after in the same source file, or by linking a binary later).
The cons of that is that you actually have to follow your contract, not much very an issue because if you don't follow your contract the compiler will somehow complain early, but in some languages code just get executed without the need to "promise its own existence" (speaking of dynamically typed languages)
I'd say any danger is eclipsed by the gains. There are some though, mostly related to refactoring.
namespace
to another, coupled with using
directives, can wreak havoc (mysterious errors, hard to spot and fix) - of course, the using
directives are bad to start off with, but no code is perfect, right?*Consider
template<class X = int> class Y;
int main()
{
Y<> * y;
}
//actual definition of the template
class Z
{
};
template<class X = Z> //vers 1.1, changed the default from int to Z
class Y
{};
The class Z
was changed afterwards as the default template argument, but the original forward declaration is still with int
.
*I've recently ran into this:
Definition:
//3rd party code
namespace A
{
struct X {};
}
and forward declaration:
//my code
namespace A { struct X; }
//3rd party code
namespace B
{
struct X {};
}
namespace A
{
using ::B::X;
}
This obviously rendered my code invalid, but the error wasn't at the actual place and the fix was, to say the least, fishy.
A forward declaration is not so much dangerous in itself, but it is a code smell. If you need a forward declaration, it means two classes are tightly coupled, which usually is bad. Thus it is an indication that your code may need refactoring.
There are some cases where it is OK to have tight coupling, e.g. the concrete states in a state pattern implementation may be tightly coupled. I would consider this OK. But in most other cases, I would improve my design before using a forward declaration.