tags:

views:

467

answers:

6

C++ headers

If I have A.cpp and A.h as well as b.h, c.h, d.h

Should I do:

in A.h:

#include "b.h"
#include "c.h"
#include "d.h"

in A.cpp:

#include "A.h"

or

in A.cpp:

#include "A.h"
#include "b.h"
#include "c.h"
#include "d.h"

Are there performance issues? Obvious benefits? Is something bad about this?

A: 

Prefer not including headers in other headers - it slows down compilation and leas to circular reference

Martin Beckett
@mgd - If I have a header that has 10 includes and the source had 10 different includes, should I just move the includes from the header to the source so the source has 20 includes?
JT
See alex's more complete answer.One exception to this is if you have precompiled headers, in that case include all the platform/framework/OS headers that will never change into one file and include that everywhere
Martin Beckett
A: 

There would be no performance issues, it's all done at compile time, and your headers should be set up so they can't be included more than once.

I don't know if there's a standard way to do it, but I prefer to include all the headers I need in source files, and include them in the headers if something in the header itself needs it (for example, a typedef from a different header)

Jeffrey Aylesworth
@Jeff - ah right, items in the header might need it. but wouldn't they get it if all headers are in the source file?
JT
+15  A: 

You should only include what is necessary to compile; adding unnecessary includes will hurt your compilation times, especially in large projects.

Each header file should be able to compile cleanly on its own -- that is, if you have a source file that includes only that header, it should compile without errors. The header file should include no more than is necessary for that.

Try to use forward declarations as much as possible. If you're using a class, but the header file only deals with pointers/references to objects of that class, then there's no need to include the definition of the class -- just use a forward declaration:

class SomeClass;
// Can now use pointers/references to SomeClass
// without needing the full definition
Adam Rosenfield
@Adam - do you have an example of forward declarations and when is appropriate to use and when not?
JT
Great advice. I would also recommend that the .c file associated with a .h includes the .h as the first include, always. This is to make sure that all your .h files can always compile on their own (instead of relying on the include order in your .c file).
Edan Maor
+1 for the last part, I previously always included the header file
Daniel
You can also use a forward declaration if you're returning `SomeClass` by value.
Frerich Raabe
+3  A: 

What Adam Rosenfield told you is spot on. An example of when you can use a forward declaration is:

#ifndef A_H_
#define A_H_

    #include "D.h"
    class B;  //forward declaration
    class C;  //forward declaration

    class A
    {
    B *m_pb;  //you can forward declare this one bacause it's a pointer and the compilier doesn't need to know the size of object B at this point in the code.  include B.h in the cpp file.
    C &m_rc;  //you can also forware declare this one for the same reason, except it's a reference.

    D m_d;    //you cannot forward declare this one because the complier need to calc the size of object D.

    };

#endif
cchampion
(I hope that builds, I didn't test it lol. let me know if you have problem with it).
cchampion
+5  A: 

The key practice here is having around each foo.h file a guard such as:

#ifndef _FOO_H
#define _FOO_H

...rest of the .h file...
#endif

This prevents multiple-inclusions, with loops and all such attendant horrors. Once you do ensure every include file is thus guarded, the specifics are less important.

I like one guiding principle Adam expresses: make sure that, if a source file just includes a.h, it won't inevitably get errors due to a.h assuming other files have been included before it -- e.g. if a.h requires b.h to be included before, it can and should just include b.h itself (the guards will make that a noop if b.h was already included previously)

Vice versa, a source file should include the headers from which it is requiring something (macros, declarations, etc), not assume that other headers just come in magically because it has included some.

If you're using classes by value, alas, you need all the gory details of the class in some .h you include. But for some uses via references or pointers, just a bare class sic; will suffice. E.g., all other things being equal, if class a can get away with a pointer to an instance of class b (i.e. a member class b *my_bp; rather than a member class b *my_b;) the coupling between the include files can be made weaker (reducing much recompilation) -- e.g. b.h could have little more than class b; while all the gory details are in b_impl.h which is included only by the headers that really need it...

Alex Martelli
Given that foo.h will still be read in every time it is included, it's not really a no-op. It'd be a no-op if you did: #ifndef _FOO_H #include "foo.h" #endif
Bill
Yeah, but that would pollute every inclusion into unreadability. To all intents and purposes, a multiply-repeated include is going to be found in the filesystem's cache, so there's no performance hit in "including" it again -- and definitely it's a no-op from the semantics viewpoint, which is what really matters.
Alex Martelli
+1  A: 

Answer: Let A.h include b.h, c.h and d.h only if it's needed to make the build succeed. The rule of thumb is: only include as much code in a header file as necessary. Anything which is not immediately needed in A.h should be included by A.cpp.

Reasoning: The less code is included into header files, the less likely you will need to recompile the code which uses the header file after doing some change somewhere. If there are lots of #include references between different header files, changing any of them will require rebuilding all other files which include the changed header file - recursivel. So if you decide to touch some toplevel header file, this might rebuild huge parts of your code.

By using forward declarations wherever possible in your header files, you reduce the coupling of the source files and thus make the build faster. Such forward declarations can be used in many more situations than you might think. As a rule of thumb, you only need the header file t.h (which defines a type T) if you

  1. Declare a member variable of type T (note, this does not include declaring a pointer-to-T).
  2. Write some inline functions which access members of an object of type T.

You do not need to include the declaration of T if your header file just

  1. Declares constructors/functions which take references or pointers to a T object.
  2. Declares functions which return a T object by pointer, reference or value.
  3. Declares member variables which are references or pointers to a T object.

Consider this class declaration; which of the include files for A, B and C do you really need to include?:

class MyClass
{
public:
    MyClass( const A &a );

    void set( const B &b );
    void set( const B *b );
    B getB();
    C getC();

private:
    B *m_b;
    C m_c;
};

You just need the include file for the type C, because of the member variable m_c. You can often remove this requirement as well by not declaring your member variables directly but using an opaque pointer to hide all the member variables in a private structure, so that they don't show up in the header file anymore.

Frerich Raabe
You're mixing A, B, and C with X, Y, and Z in your example.
Bill
@Bill: You're right, I adjusted the example to say A, B, C now.
Frerich Raabe