General hints on what to #include in what

T

The Cool Giraffe

One thing i do know for sure. When one creates a CPP file,
one needs to include the H file. Now, having said that, i
wonder if there are some general hints, requirements or
standard guide lines on what and how to include.

Suppose that we have a project consisting of a number of
classes and structs. Some of them using the others, some
using all of them. What is a good approach when including?
 
J

John Harrison

The said:
One thing i do know for sure. When one creates a CPP file,
one needs to include the H file. Now, having said that, i
wonder if there are some general hints, requirements or
standard guide lines on what and how to include.

Suppose that we have a project consisting of a number of
classes and structs. Some of them using the others, some
using all of them. What is a good approach when including?

It's a good question. Here's a good set of rules.

1) Every header file should be able to be compiled on its own. So if
your header defines a class which uses std::string, say, then that
header file should include <string>. If it uses MyStruct then it should
include "MyStruct.h". It is really annoying to have a header file and
then have to work out what other header files you have to include before
you include the first header file (unfortunately Microsoft are bad
offenders in this regard).

2) Assuming that you are working on the one header file for each cpp
file (which is a reasonable rule as well) then the best way to insure
that you follow rule 1 is to include a header file as the very first
header file in it's corresonding cpp file. So if you have widget.h and
widget.cpp then widget.cpp should include widget.h as its very first
include, before absolutely anything else. That way if widget.h isn't
including something that it should you will find out because of a
compiler error.

3) But only include what you need to get compilation working. It's a
mistake to include "X.h" in "Y.h" just because you think that whoever is
using "Y.h" will probably want "X.h" as well. Leave that decision to the
person actually including the header files.

4) After you've followed rules 1 and 2 then include every header you
need to get the compilation of each cpp file working, but again, no more.

Unfortunately there is no automatic way to ensure that you don't include
stuff you don't need in either cpp or header files, so I usually review
header and cpp files from time to time to make sure I'm not including
anything I don't need.

john
 
G

Gavin Deane

One thing i do know for sure. When one creates a CPP file,
one needs to include the H file. Now, having said that, i
wonder if there are some general hints, requirements or
standard guide lines on what and how to include.

Suppose that we have a project consisting of a number of
classes and structs. Some of them using the others, some
using all of them. What is a good approach when including?

A few rules I believe are worth sticking to with headers:

1. When you have classes and structs that know about other classes and
structs, use forward declarations whenever you can to reduce the
number of headers included in other headers. See
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.11
and the ones that follow it. Although that FAQ talks about resolving a
circular dependency, it describes the general principle of forward
declarations and how they are used.

2. The point above will hopefully reduce the number of includes you
need within a particular header. However, *always* make sure that a
header *does* include everything it needs to be a stand-alond
compileable unit. A source file that contains nothing except #include
"my_header.h" should compile with no errors. Example (untested but I
think simple enough to make the point):

// my_header.h original
struct person
{
std::string name;
};

// test_my_header.cpp original
#include "my_header.cpp"

test_my_header.cpp will not compile. You will get an error because the
compiler does not know what std::string is. One solution is to change
test_my_header.cpp:

// test_my_header.cpp modified in an un-good way
#include <string>
#include "my_header.cpp"

Now it compiles. But if you follow this approach, you force yourself
and everybody else who ever uses my_header.h to have to remember to
include <string> before my_header.h *every time* they use it. Much
better is to modify my_header.h

// my_header.h modified in a good way
#include <string>
struct person
{
std::string name;
};

Now the original version of test_my_header.cpp will compile cleanyl,
and users of your header can simply include it without needing to jump
through any other hoops.

3. Always use include guards in every header. Doesn't seem to be a FAQ
on that, but wikipedia will suffice http://en.wikipedia.org/wiki/Include_guard.
No, my example above does not follow this advice. That was for clarity
in making the point. In the real world I would certainly put an
include guard in my_header.h.

4. Don't put using directives or using declarations in headers (at
least not at global scope - they can be necessary inside class
definitions). Using directives and declarations have pros and cons and
whether to use them or not needs to be judged on a case by case basis.
If you put one in a header, you force its use on everyone who ever
includes that header, whether they want it or not. Don't do that - let
them decide for themselves.

HTH
Gavin Deane
 
T

The Cool Giraffe

John Harrison wrote/skrev/kaita/popisal/schreibt :
The Cool Giraffe wrote:

It's a good question. Here's a good set of rules.

1) Every header file should be able to be compiled on its own. So if
your header defines a class which uses std::string, say, then that
header file should include <string>. If it uses MyStruct then it
should include "MyStruct.h". It is really annoying to have a header
file and then have to work out what other header files you have to
include before you include the first header file (unfortunately
Microsoft are bad offenders in this regard).

2) Assuming that you are working on the one header file for each cpp
file (which is a reasonable rule as well) then the best way to insure
that you follow rule 1 is to include a header file as the very first
header file in it's corresonding cpp file. So if you have widget.h and
widget.cpp then widget.cpp should include widget.h as its very first
include, before absolutely anything else. That way if widget.h isn't
including something that it should you will find out because of a
compiler error.

3) But only include what you need to get compilation working. It's a
mistake to include "X.h" in "Y.h" just because you think that whoever
is using "Y.h" will probably want "X.h" as well. Leave that decision
to the person actually including the header files.

4) After you've followed rules 1 and 2 then include every header you
need to get the compilation of each cpp file working, but again, no
more.
Unfortunately there is no automatic way to ensure that you don't
include stuff you don't need in either cpp or header files, so I
usually review header and cpp files from time to time to make sure
I'm not including anything I don't need.


This pretty much answered my question. Thanks!
 
M

Marcus Kwok

John Harrison said:
1) Every header file should be able to be compiled on its own. So if
your header defines a class which uses std::string, say, then that
header file should include <string>. If it uses MyStruct then it should
include "MyStruct.h". It is really annoying to have a header file and
then have to work out what other header files you have to include before
you include the first header file (unfortunately Microsoft are bad
offenders in this regard).

2) Assuming that you are working on the one header file for each cpp
file (which is a reasonable rule as well) then the best way to insure
that you follow rule 1 is to include a header file as the very first
header file in it's corresonding cpp file. So if you have widget.h and
widget.cpp then widget.cpp should include widget.h as its very first
include, before absolutely anything else. That way if widget.h isn't
including something that it should you will find out because of a
compiler error.

3) But only include what you need to get compilation working. It's a
mistake to include "X.h" in "Y.h" just because you think that whoever is
using "Y.h" will probably want "X.h" as well. Leave that decision to the
person actually including the header files.

4) After you've followed rules 1 and 2 then include every header you
need to get the compilation of each cpp file working, but again, no more.

Unfortunately there is no automatic way to ensure that you don't include
stuff you don't need in either cpp or header files, so I usually review
header and cpp files from time to time to make sure I'm not including
anything I don't need.

While I agree in general, sometimes you may need to include additional
headers in order to have a truly portable program. Since standard
library headers are allowed to include other standard headers, it makes
it easy to forget one.

The main example I can think of is omitting #include <ostream> when it
is needed, since many implementations will implicitly include it when
#including <iostream>. I had a program that used std::endl and compiled
fine on Windows. When I had to move it to HP-UX, I found that I had to
explicitly #include <ostream> as well as <iostream>.
 
R

Roland Pibinger

Here's a good set of rules.

1) Every header file should be able to be compiled on its own. So if
your header defines a class which uses std::string, say, then that
header file should include <string>. If it uses MyStruct then it should
include "MyStruct.h".

'uses' means uses as data member. Otherwise a forward declaration is
sufficient, even if you pass or return by value.
2) Assuming that you are working on the one header file for each cpp
file (which is a reasonable rule as well) then the best way to insure
that you follow rule 1 is to include a header file as the very first
header file in it's corresonding cpp file.

But do this only to test header includes. Otherwise always include
system and library headers before your own.

Best regards,
Roland Pibinger
 
M

Marcus Kwok

Gavin Deane said:

My guess is that if you have some funky #defines, then it would prevent
changing the meaning of system headers. However, IIRC, you are only
allowed to redefine keywords if you do not include those headers.
 
G

Gavin Deane

My guess is that if you have some funky #defines, then it would prevent
changing the meaning of system headers. However, IIRC, you are only
allowed to redefine keywords if you do not include those headers.

Doesn't sound like much of a reason to me. I would expect redefining
keywords to be something that happens rarely, if ever - certainly not
commonplace enough to be justifiable as the basis for this sort of
guideline.

But then, Roland Pibinger could have had a different reason in mind.

Gavin Deane
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top