General hints on what to #include in what

Discussion in 'C++' started by The Cool Giraffe, Feb 25, 2007.

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

    --
    Vänligen Kerstin Viltersten
    (The Cool Giraffe)
     
    The Cool Giraffe, Feb 25, 2007
    #1
    1. Advertising

  2. The Cool Giraffe wrote:
    > 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
     
    John Harrison, Feb 25, 2007
    #2
    1. Advertising

  3. The Cool Giraffe

    Gavin Deane Guest

    On 25 Feb, 10:49, "The Cool Giraffe" <> wrote:
    > 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
     
    Gavin Deane, Feb 25, 2007
    #3
  4. John Harrison wrote/skrev/kaita/popisal/schreibt :
    > The Cool Giraffe wrote:


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



    This pretty much answered my question. Thanks!

    --
    Vänligen Kerstin Viltersten
    (The Cool Giraffe)
     
    The Cool Giraffe, Feb 25, 2007
    #4
  5. The Cool Giraffe

    Marcus Kwok Guest

    John Harrison <> wrote:
    > 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>.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, Feb 27, 2007
    #5
  6. On Sun, 25 Feb 2007 11:05:25 GMT, John Harrison wrote:
    >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
     
    Roland Pibinger, Feb 27, 2007
    #6
  7. The Cool Giraffe

    Gavin Deane Guest

    On 27 Feb, 22:06, (Roland Pibinger) wrote:
    > >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.


    Why?

    Gavin Deane
     
    Gavin Deane, Feb 28, 2007
    #7
  8. The Cool Giraffe

    Marcus Kwok Guest

    Gavin Deane <> wrote:
    > On 27 Feb, 22:06, (Roland Pibinger) wrote:
    >> >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.

    >
    > Why?


    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.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, Feb 28, 2007
    #8
  9. The Cool Giraffe

    Gavin Deane Guest

    On 28 Feb, 18:35, (Marcus Kwok) wrote:
    > GavinDeane<> wrote:
    > > On 27 Feb, 22:06, (Roland Pibinger) wrote:


    <snip>

    > >> always include
    > >> system and library headers before your own.

    >
    > > Why?

    >
    > 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
     
    Gavin Deane, Feb 28, 2007
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Spamtrap

    Need some hints on speeding up

    Spamtrap, Aug 11, 2004, in forum: Perl
    Replies:
    1
    Views:
    372
    Jim Gibson
    Aug 12, 2004
  2. Gertraud
    Replies:
    2
    Views:
    401
    Gertraud
    Mar 17, 2005
  3. Andreas Bogenberger
    Replies:
    3
    Views:
    931
    Andreas Bogenberger
    Feb 22, 2008
  4. Replies:
    2
    Views:
    467
  5. Replies:
    9
    Views:
    169
    John Wilger
    Mar 16, 2007
Loading...

Share This Page