views:

356

answers:

7

Suppose I have a file X.h which defines a class X, whose methods are implemented in X.cc. The file X.h includes a file Y.h because it needs Y to define class X. In X.cc, we can refer to Y because X.h has already included Y.h. Should I still include Y.h in X.cc ?

I understand that I don't need to and I can depend on header guards to prevent multiple inclusions. But on the one hand, including Y.h makes X.cc a little more independent of X.h (can't be completely independent of course). What is the accepted practice?

Another example: including <iostream> in both .h and .cc files. I see some people do this and some don't.

+1  A: 

It doesn't really matter very much [at least, not unless you have a gigantic project], but I would probably lean towards including it.

SamB
It definitely can matter. `#include`s in headers increase build times.
John Dibling
+1  A: 

I think you should. As your code grows and some implementation changes, some includes my be removed from a header file that is included by another header file that is included in some header file... It might get real nasty to find out why something that has nothing to do with changes you (or someone else) made isn't working anymore.

FRotthowe
Eh? How does adding a redundant #include directive help this?
Beta
@Beta: Because if you have the #include in the .cc, nobody is going to yank it from there because the .h no longer needs that #include... so the .cc still gets the .h it needs included.
SamB
@SamB: 1) When you remove "#include X" from A.hh and A.cc still needs it, you add it to A.cc; if you forget, the compiler will remind you at once. Adding it beforehand is no easier than adding it when you need it. 2) FRotthowe is talking about breaking B because B needs X and gets it by #including A.hh (perhaps through a chain of headers), and keeping a redundant #include in A.cc does *nothing* to prevent this.
Beta
Ah, sorry. I got the question wrong I guess. Got confused with all the Xs and Ys...Well, maybe then the include shouldn't be in the header in the first place. A forward declaration should have the same effect.
FRotthowe
+5  A: 

I would suggest including the header include for Y in X.cc even if it seems redundant. It gives you the advantage of being very explicit as to your dependencies.

As a related note, you should always #include the associated header for a cpp file as the first #include'd file. (The first include in X.cpp should be X.h) This guarantees that the header include the proper files to resolve its own dependencies, otherwise you could inadvertently be relying on the ordering of includes in your source file.

cpalmer
+1 for X.h first in X.cpp
quamrana
This seems strange to me, because you have to walk the chain of header files to **fully** determine dependencies, so the list of includes in your .cc file is only partial anyway. This being the case, why doubly include things?
Scott Smith
+8  A: 

Be minimal. In headers, prefer forward declarations to full definitions. Use iosfwd instead of ostream, for example.

That said, X.h and X.cc represent the same logical unit. If your dependency on Y.h ever changed (for example, turned it into a forward declaration), you'd be changing the class anyway. So you can move #include "Y.h" to X.cc justifiably.

In other words, X.cc and X.h go hand in hand. X.cc can reliably assume what's in X.h. So there's no need to re-include something if X.h does.

Dependencies where you 'include it anyway' occur with resources other than your own. For example, if you needed Z.h, you'd include it even if Y.h does. X.h does not get to reliably assume the contents of Y.h because X.h doesn't go with Y.h, it uses it.

GMan
A: 

From your example I would only include X.h in X.cc only to reduce the number of includes. Yes, in the more general case where you have A.cc including X.h, and as a side effect being able to reference stuff in Y.h, when you can remove X.h you find yourself having to manually add Y.h because you didn't add it before. At least the compiler will be on your case and remind you.

In the case of <iostream> you need it when you need it, whether in a header file or a module.

quamrana
+3  A: 

I'm not sure why doing so would be a good practice.

On the other hand, not including unnecessary files in X.h is something I consider to be a very good practice.

For example, in the following scenario:

X.h

#include "Y.h"

class X
{
private:
    Y * m_pY;

public:
    X();
    ~X();
}

It would be sufficient to forward declare Y. Clients of class X need not incur the expense of including the header file for Y:

X.h

class Y; // include Y.h in X.cc instead

class X
{
private:
    Y * m_pY;

public:
    X();
    ~X();
}

This is possible in the header file, because the declaration of class X doesn't require specific details about Y (e.g. the size of an instance); only that Y is a class. Further, clients of class X never deal with the type Y, since it's not part of X's public interface.

For large projects, avoiding unnecessary include directives in header files can significantly improve build times.

It can also avoid polluting the namespace of users of your class with symbols from your private/implementation classes.

Scott Smith
A: 

#include statements in header files can increase compilation times. For toy applications or large systems with only one dependency like you describe this won't be a problem. But as your application grows, so will compilation times. One resolution under MSVC is to use precompiled headers (which bring their own set of headaches), or to eliminate all #include statements in headers. The latter is my default approach, and I try first to use forward declarations where needed:

y.h :

class Y {public: int foo_; };

x.h :

class Y;
class X { public: Y* y_; };

main.cc :

#include "y.h"
#include "x.h"

int main()
{
  X x;
  return 0;
}

If using forward declares isn't possible, just remember that #include does nothing more than bring the contents of the specified file to that point, and this can be done just as easily from the cc file as from the header:

y.h :

class Y {public: int foo_; };

x.h :

class X {public: Y y_; }; // note this declaration requires a concrete type for Y

main.cc :

#include "y.h"
#include "x.h"

int main()
{
  X x;
  return 0;
}
John Dibling