J
Juha Nieminen
Multiple inclusion of the same header file can cause the compilation
to fail because of multiple definitions of the same type. That's why
it's standard practice to write all headers like this:
// SomeClass.hh
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH
class SomeClass
{
...
};
#endif
In complex projects recursive inclusion happens. It can be a rather
long chain of headers including other headers in a loop, and it may
be easy to miss.
The problem is that when this happens, the compiler errors are
usually very confusing. In the worst case (this has happened to me)
the compiler starts giving errors on places which have so far
compiled without problems and you haven't touched for weeks. It can
easily be really confusing why the compiler suddenly started to
complain about something you haven't even modified. Unless you have
experienced it before, it can be really hard to guess that the
problem is in a recursive inclusion which formed when you wrote
that one #include in a seemingly unrelated header. (Depending on
the compiler and the project settings it may be completely unexpected
what will "break" first because of that.)
I was thinking: In most cases when this problem has happened to me,
it was easy to fix by removing the #include and replacing it with a
pre-declaration of the class, as this usually has happened only when
I use references/pointers to that class instead of instances. Thus if
all headers were written like this:
// SomeClass.hh
class SomeClass;
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH
class SomeClass
{
...
};
#endif
then recursive inclusion would not be a problem. If you are only
using pointer/references, then everything will compile and work ok.
And even if you are using the class as a member variable and you
simply can't do that, you will most probably get a more meaningful
error message, like "error: field `x' has incomplete type" (now you
only have to understand that "incomplete type" refers to the type
having only been pre-declared).
Can anyone think of a drawback of doing this?
to fail because of multiple definitions of the same type. That's why
it's standard practice to write all headers like this:
// SomeClass.hh
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH
class SomeClass
{
...
};
#endif
In complex projects recursive inclusion happens. It can be a rather
long chain of headers including other headers in a loop, and it may
be easy to miss.
The problem is that when this happens, the compiler errors are
usually very confusing. In the worst case (this has happened to me)
the compiler starts giving errors on places which have so far
compiled without problems and you haven't touched for weeks. It can
easily be really confusing why the compiler suddenly started to
complain about something you haven't even modified. Unless you have
experienced it before, it can be really hard to guess that the
problem is in a recursive inclusion which formed when you wrote
that one #include in a seemingly unrelated header. (Depending on
the compiler and the project settings it may be completely unexpected
what will "break" first because of that.)
I was thinking: In most cases when this problem has happened to me,
it was easy to fix by removing the #include and replacing it with a
pre-declaration of the class, as this usually has happened only when
I use references/pointers to that class instead of instances. Thus if
all headers were written like this:
// SomeClass.hh
class SomeClass;
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH
class SomeClass
{
...
};
#endif
then recursive inclusion would not be a problem. If you are only
using pointer/references, then everything will compile and work ok.
And even if you are using the class as a member variable and you
simply can't do that, you will most probably get a more meaningful
error message, like "error: field `x' has incomplete type" (now you
only have to understand that "incomplete type" refers to the type
having only been pre-declared).
Can anyone think of a drawback of doing this?