Thread: Best Practices For Includes

  1. #1
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507

    Best Practices For Includes

    Hey, I was wondering your opinion on the best practices for including outside headers in a class declaration/implementation files.

    IE

    SomeClass.h

    Code:
    class SomeClass
    {
    //...
    };
    and SomeClass.cpp

    //Some implmentation.

    For declaring local variables of some outside type, for instance an stl::queue, should I #include<queue> in the .h file, or just in the cpp file? Or does it really matter? I've seen it both ways and was wondering if there was a "proper" way to do it. Also I've heard it is not good to use a using namespace in either the .h/.cpp file. IE just use the :: operator to bring the types into scope? Why is this best.

    Thanks.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    I'd suggest the best practice is minimising unnecessary compilation dependencies. With header files that means only including them where they are absolutely needed, and not including them otherwise. That means not including a header "just in case" it is needed by some future code.

    A common case in which programmers often include headers unnecessarily is when a forward declaration is sufficient (eg a function that accepts or returns a reference or a pointer to a type, rather than returning by value).

    A worst case I have seen was a header named "globals.h" which included every several hundred other header files. The "case" for doing this was that the programmer could include "globals.h" and did not need to muck around working out which headers were needed for any particular source file. This was caught out when the same programmer requested very high-end machines for doing the builds. It turned out that the compile/build time for the complete system had grown to about three weeks. By going through - over a week - and deleting the "globals.h", and then ensuring that no file (source file or otherwise) included any header file it didn't need to, the total build time was reduced to about three hours. Without changing hardware.

    The problem with "using namespace" directives is that they cannot be reversed. Putting them into a header file can therefore cause ambiguity in all source files that include that header. This is particularly relevant in cases where two distinct namespaces have something with the same name: if a "using namespace" directive is in force for both namespaces, then the common names must always be explicitly named (using namespace::name form). If a source file is evolved, and needs a new header that has a "using namespace" directive within it, then unrelated code in that source file can become un-compileable.

    "using namespace" directives in source files (.cpp) can be acceptable, but that's because the programmer is under control. That is not the case with header files.

    Incidentally, the "::" operator does not bring types into scope. [Yes, I realise some texts and teachers describe it that way, but they're wrong]. The "namespace::name" form is a completely unambiguous name. The "name" form causes the compiler to look in nominated namespaces for candidates which match that name (hence the potential ambiguity if multiple "using namespace" directives are in force).

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Putting them into a header file can therefore cause ambiguity in all source files that include that header.
    Also in other headers that are included after the header which brings things into global namespace. E.g allegro users, if they also use <iostream> with using namespace std; sometimes end up getting a conflict between the iostream format flag fixed and fixed typedef in allegro. Resulting in a forum post: Why do I get error in allegro header? Simple fix, remove using declarations from headers and std::fixed won't be visible to allegro headers any more.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If forward declarations can do, then it's also a good idea to use them.
    But if not, it is also a good idea to make sure all headers include the necessary dependencies. Otherwise you will get a mess with header X requiring header Y, requiring header Z, and the headers all have to be included prior to including these headers leading to awkward and difficult code to maintain.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    it is also a good idea to make sure all headers include the necessary dependencies
    But in my opinion, only the dependencies for that header file only! Dependency is a local issue, and should not be globalized.

    Since before compilation all headers #include-d are parsed, I like to limit the number of declarations/implementations in a header file to consume less time. This parsing overhead can be huge!
    Last edited by MarkZWEERS; 03-08-2009 at 11:15 AM.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    So true. For that header only.
    And making sure that header has as few dependencies as possible is also such a great idea since it limits the amount of headers it needs to include. Among other benefits.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The general rule applies for both header files and code modules: if a source file (.h, .c, or .cpp) requires a declaration from header X.h, then that source file should include X.h.

    Forward declarations are optimizations: don't use them until you've proven you need them. Some strange circularly-dependent data types may require forward declarations, but using them just to speed up compilation has the same pitfalls as other optimizations. Only do it if you need to.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by brewbuck
    Forward declarations are optimizations: don't use them until you've proven you need them. Some strange circularly-dependent data types may require forward declarations, but using them just to speed up compilation has the same pitfalls as other optimizations. Only do it if you need to.
    Sutter and Alexandrescu disagree, recommending in C++ Coding Standards item #22 that one should "prefer forward declarations except where you really need a type's definition". What pitfalls do you find with the use of forward declarations when they suffice?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by laserlight View Post
    Sutter and Alexandrescu disagree, recommending in C++ Coding Standards item #22 that one should "prefer forward declarations except where you really need a type's definition". What pitfalls do you find with the use of forward declarations when they suffice?
    It requires thinking. You have to decide whether you can get away with a forward declaration or if you need the entire type. Thinking is generally bad, because when you think, you can make a mistake.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by brewbuck
    It requires thinking. You have to decide whether you can get away with a forward declaration or if you need the entire type. Thinking is generally bad, because when you think, you can make a mistake.
    However, the design of the classes involved, and the decisions to divide them into header and source files requires thought along the same lines as that required to decide whether a forward declaration will suffice or if the class definition is required.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by laserlight View Post
    However, the design of the classes involved, and the decisions to divide them into header and source files requires thought along the same lines as that required to decide whether a forward declaration will suffice or if the class definition is required.
    This is only true if you are in control of all the code. A header file could have "stuff" in it which actually changes program behavior depending on whether it was included. For instance, it could define static objects (for what purpose? who knows, it isn't your code)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by brewbuck
    This is only true if you are in control of all the code. A header file could have "stuff" in it which actually changes program behavior depending on whether it was included. For instance, it could define static objects (for what purpose? who knows, it isn't your code)
    I agree, but that does not invalidate the advice to prefer forward declarations to class definitions. Remember, forward declarations can be provided via a header file as well, as is the case for <iosfwd>.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by laserlight View Post
    I agree, but that does not invalidate the advice to prefer forward declarations to class definitions. Remember, forward declarations can be provided via a header file as well, as is the case for <iosfwd>.
    I guess I just disagree. Forward declarations don't provide any benefit except enhanced compilation speed. IMHO, this is just an optimization.

    EDIT: Of course, like I said before, there are cases where you need forward declarations to define circularly-dependent types. But in most cases, that's a "code smell."
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  14. #14
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    A header file could have "stuff" in it which actually changes program behavior depending on whether it was included. For instance, it could define static objects (for what purpose? who knows, it isn't your code)
    But if a header file declares static objects which could impact its usage in your code, the library is not useful? If you don't know what's in the library, you don't know there static objects either.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. coding practices
    By pobri19 in forum C++ Programming
    Replies: 2
    Last Post: 07-17-2008, 04:56 PM
  2. deque best practices
    By George2 in forum C++ Programming
    Replies: 10
    Last Post: 03-02-2008, 08:11 PM
  3. Best programming practices for multiple connections
    By vasillalov in forum Networking/Device Communication
    Replies: 8
    Last Post: 10-09-2007, 10:14 PM
  4. Copy constructors; Best practices (and private)
    By Mario F. in forum C++ Programming
    Replies: 15
    Last Post: 06-23-2006, 04:42 PM
  5. read-only data members. A question of good practices
    By Mario F. in forum C++ Programming
    Replies: 11
    Last Post: 06-19-2006, 04:35 AM