On 14.11.2013 22:34, ouroboros84 wrote:
[snip]
> a.cpp
>
> #include "a.hpp"
> //needed or I can leave it out, since B is included already in a.hpp?
> #include "b.hpp"
>
> B A::get_b()
> {
> return _b;
> }
In this case the full class B definition is not needed for class A's
public interface. So there is a possibility that class A will be changed
so that [b.hpp] is not needed for [a.hpp]. However, changing [a.hpp]
will usually be accompanied by a corresponding change of [a.cpp], so
there's problem with THIS file, whatever you decide.
The main problem is with client code. A programmer using [a.hpp] cannot
know whether [b.hpp] is guaranteed made available or is just present as
an implementation aspect that might be changed at any time. That's
because the complete class B definition is not needed for A's /public/
interface, only for its implementation, and so some optimization of
class A (e.g. for build time) might result in [b.hpp]'s removal.
So if I was concerned about this kind of problem then I would document
in some way whether [b.hpp] is present by design or as just an
implementation aspect.
* * *
In some cases you absolutely know that a header will be made available
by some other header. For example, a header that exposes something that
involves Windows API things will, as a rule, guaranteed include
<windows.h>. But that does not mean that client code can avoid including
<windows.h>. On the contrary, that Microsoft header, the "mother of all
headers", provides a set of declarations that depends strongly on
various macro symbols, plus that a great many of the declarations
themselves depend on various macro symbols. Thus to ensure consistent
declarations and a consistent set of declarations, it is a good idea to
include this header before including headers that depend on it. Other
3rd party headers may be similarly badly designed.
* * *
To ensure that headers are free-standing (that they're "idempotent")
it's a good idea to include each header at the top in /some/ [.cpp]
file. For header only modules I use a dummy [.cpp] file. E.g.,
[blahblah.h] is included by [blahblah.h.dummy.cpp], if it isn't included
by a real implementation file [blahblah.cpp].
With some toolsets (in particular Microsoft's) this necessitates turning
off librarian warnings about unused stuff.
Also note that this practice ties in with the previous section, ensuring
that those headers that need some H do include it.
* * *
Microsoft's precompiled header feature, which is on by default in a
Visual Studio project, can make incorrect code compile and can cause
errors with correct code. It's no big deal to adjust the code but it
means that code compiled with this feature may not necessarily work with
some other compiler. I do not know of any good solution.
Cheers & hth.,
- Alf