Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Headers - Best practice when including

Tags:

c++

header

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?

like image 860
JT. Avatar asked Nov 09 '09 01:11

JT.


3 Answers

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
like image 173
Adam Rosenfield Avatar answered Nov 17 '22 08:11

Adam Rosenfield


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...

like image 26
Alex Martelli Avatar answered Nov 17 '22 07:11

Alex Martelli


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
like image 3
cchampion Avatar answered Nov 17 '22 07:11

cchampion