views:

218

answers:

4

Suppose I have a solution with 3 projects X,Y, and E.

E will generate an executable and X and Y will generate static libraries such that Y includes the header files of X and E includes the header files of Y.

Now, my question is: why do I have to include the directory of the header files of X in E?

+4  A: 

Here's why:

  1. It is possible that some function in project Y takes an argument (or returns a value) which is of a type declared in X.
  2. If so, the compiler may have to create these argument (or return value) objects while compiling E.
  3. If that's the case, header files from X are absolutely needed in E.
Frederick
+1  A: 

It is sometimes possible to restructure header files for C++ to use forward declarations to avoid the situation that you describe. Here is an example: C++ header dependency tricks.

A simple case:

X.h

class X {
  //...
};

Y.h

// #include <X.h> -- remove this
class X; // add forward declaration
class Y {
  X *m_px; // must be a pointer, not a value,
           // otherwise the size of X would need to be known
  //...
};

Y.cpp

#include <X.h> // need to add it here
//...
gwell
I tried forward declaration, but the compiler still tries to open a header file of `X` included in `Y`
Jacob
A: 

Short answer: "Why do I have to include the directory of the header files of X in E?"... You shouldn't. Client's of Y should not have to know that Y depends on X.


Long answer: You need to include the header of X in E only if the interface (signatures) of Y makes use of things declared in the header of X. But if the header of Y were "properly constructed", then they would include the headers of X in the Y header itself and you wouldn't have to include the X header in E explicitly (including the Y header would automatically include the X header).

By "Properly constructed" I meant that if the signatures in Y1.h in Y depend on (say) X3.h and X7.h, then Y1.h should include those files (directly of indirectly). This way, any client of Y1.h would not have to know what it's dependencies are and have to include those dependencies separately as a result. As a simple test, a .cpp consisting of the following line should compile without issues:

#include "Y1.h"

A good practice is to #include "Y1.h" before including any other file in Y1.cpp. If Y1.h is missing dependencies, the compiler will let you know.

Vulcan Eager
So how would it be "properly constructed"? And yes the signatures of `Y` uses types declared in `X`.
Jacob
+1  A: 

You can avoid this situation if you construct Y such that its dependencies on X are completely encapsulated. This may or may not be possible depending on the specifics of X and Y. But if the interface the Y presents to E doesn't need to have any details of X in it, then the E project shouldn't need to even indirectly include headers from X. In thins case only the implementation files of Y (the .c or .cpp files) would include headers from X. Using forward declarations for types in X in the Y headers could help achieve this encapsulation of X in Y.

This is a good goal to reach for, but it might not always be possible and even when it is possible it might be more effort than you (or your management) might want to put forth.

Michael Burr