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"
#inc开发者_JAVA技巧lude "d.h"
Are there performance issues? Obvious benefits? Is something bad about this?
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
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...
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
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
- Declare a member variable of type
T
(note, this does not include declaring a pointer-to-T
). - 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
- Declares constructors/functions which take references or pointers to a
T
object. - Declares functions which return a
T
object by pointer, reference or value. - 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.
Prefer not including headers in other headers - it slows down compilation and leas to circular reference
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)
精彩评论