Tuesday, August 22, 2017

Reducing #includes in header

In C++, '#include' is an easy way to import other module.

But we need to consider the side-effect of #include. It may be big deal some time.

for example,
file: module_a.hpp
------------------------------------------
class ModuleA
{
    ...
    ...
};
file: module_a.cpp
------------------------------------------
#include "module_a.hpp"
...
...
file: module_b.hpp
------------------------------------------

#include "module_a.hpp"

class ModuleB
{
    ModuleA module_a;
    ...
    ...
};
file: module_b.cpp
------------------------------------------
#include "module_b.hpp"
...
...

file: main.cpp
------------------------------------------

#include "module_b.hpp"

int argc, char *argv[])
{
    ModuleB module_b;

    ...
    ...
}

...What's wrong??
C++ programmer always do like this.

Then let me show another approach.

file: module_a.hpp
------------------------------------------
class ModuleA
{
    ...
    ...
};
file: module_a.cpp
------------------------------------------
#include "module_a.hpp"
...
...

file: module_b.hpp
------------------------------------------
#include <memory>
class ModuleA;

class ModuleB
{
    std::unique_ptr<ModuleA> module_a;
    ...
    ...
};
file: module_b.cpp
------------------------------------------
#include "module_b.hpp"
#include "module_a.hpp"

...
...

file: main.cpp
------------------------------------------
#include "module_b.hpp"

int argc, char *argv[])
{
    ModuleB module_b;

    ...
    ...
}

The point is the position of '#include "module_a.hpp"'.
Include-dependencies are different.

In the first pattern, the dependency is,
main.cpp --> module_b.hpp --> module_a.hpp
module_b.cpp --> module_b.hpp --> module_a.hpp
module_a.cpp --> module_a.hpp

The second pattern,
main.cpp --> module_b.hpp
module_a.cpp --> module_a.hpp
module_b.cpp --> module_b.hpp
             --> module_a.hpp

If module_a.hpp is modified, the first pattern needs all files to be re-compiiled.
The second pattern needs module_a.cpp, module_b.cpp to be re-compiled.

It looks a small matter in this example, but in big project, it will make a significant difference of buiding time.

Generally, it's not recommended including file in header.
except these cases.
- Headers of library. It will not be modified in future.
- Templates. We need to include template to instanciate the actual declaration.
- Parent class to inherit.







No comments:

Post a Comment

It&#39;s magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'. 'std::bind' makes a instance of 'std::fun...