views:

221

answers:

4

Hello, I have a static library that I am building in C++. I have separated it into many header and source files. I am wondering if it's better to include all of the headers that a client of the library might need in one header file that they in turn can include in their source code or just have them include only the headers they need? Will that cause the code to be unecessary bloated? I wasn't sure if the classes or functions that don't get used will still be compiled into their products.

Thanks for any help.

+2  A: 

what about giving both choices:

#include <library.hpp> // include everything
#include <library/module.hpp> // only single module

this way you do not have one huge include file, and for your separate files, they are stacked neatly in one directory

aaa
+1  A: 

It depends on the library, and how you've structured it. Remember that header files for a library, and which pieces are in which header file, are essentially part of the API of the library. So, if you lead your clients to carefully pick and choose among your headers, then you will need to support that layout for a long time. It is fairly common for libraries to export their whole interface via one file, or just a few files, if some part of the API is truly optional and large.

A consideration should be compilation time: If the client has to include two dozen files to use your library, and those includes have internal includes, it can significantly increase compilation time in a big project, if used often. If you go this route, be sure all your includes have proper include guards around not only the file contents, but the including line as well. Though note: Modern GCC does a very good job of this particular issue and only requires the guards around the header's contents.

As to bloating the final compiled program, it depends on your tool chain, and how you compiled the library, not how the client of the library included header files. (With the caveat that if you declare static data objects in the headers, some systems will end up linking in the objects that define that data, even if the client doesn't use it.)

In summary, unless it is a very big library, or a very old and cranky tool chain, I'd tend to go with the single include. To me, freezing your current implementation's division into headers into the library's API is bigger worry than the others.

MtnViewMark
+1  A: 

In general, when linking the final executable, only the symbols and functions that are actually used by the program will be incorporated. You pay only for what you use. At least that's how the GCC toolchain appears to work for me. I can't speak for all toolchains.

If the client will always have to include the same set of header files, then I think it's okay to provide a "master" header file that includes others, for the sake of convenience. But make it so that the client can also choose to include only what is needed.

To reduce compile times in large projects, it's common practice to include the least amount of headers as possible to make a unit compile.

Emile Cormier
A: 

Keep in mind that each source file that you compile involves an independent invocation of the compiler. With each invocation, the compiler has to read in every included header file, parse through it, and build up a symbol table.

When you use one of these "include the world" header files in lots of your source files, it can significantly impact your build time.

There are ways to mitigate this; for example, Microsoft has a precompiled header feature that essentially saves out the symbol table for subsequent compiles to use.

There is another consideration though. If I'm going to use your WhizzoString class, I shouldn't have to have headers installed for SOAP, OpenGL, and what have you. In fact, I'd rather that WhizzoString.h only include headers for the types and symbols that are part of the public interface (i.e., the stuff that I'm going to need as a user of your class).

As much as possible, you should try to shift includes from WhizzoString.h to WhizzoString.cpp:

OK:

// Only include the stuff needed for this class
#include "foo.h"  // Foo class
#include "bar.h"  // Bar class

public class WhizzoString
{
    private Foo   m_Foo;
    private Bar * m_pBar;
       .
       .
       .
}

BETTER:

// Only include the stuff needed by the users of this class
#include "foo.h"  // Foo class

class Bar; // Forward declaration

public class WhizzoString
{
    private Foo   m_Foo;
    private Bar * m_pBar;
       .
       .
       .
}

If users of your class never have to create or use a Bar type, and the class doesn't contain any instances of Bar, then it may be sufficient to provide only a forward declaration of Bar in the header file (WhizzoString.cpp will have #include "bar.h"). This means that anyone including WhizzoString.h could avoid including Bar.h and everything that it includes.

Scott Smith
@Scott Smith: Good point! Thanks!
csmithmaui