2
//Foo.h
#include <string>
struct Foo;

//main.cpp
#include "Foo.h"
int main(int argc, char *argv[])
{
  std::string s = "hello";
}

The problem I have with this code is that #include <string> leaks into main.cpp. #include <string> is needed in main.cpp to compile but if in a future version Foo.h doesn't need string anymore, main.cpp will not compile.

Is there a way to prevent this?

Edit: I know that I can manage this on my own by always including every file that I need but I am working in a team and everyone does their own thing and it is a complete mess. So I was wondering if there is a way to force this.

Comments seem to indicate that we have to manage it manually. I guess this answers my question.

indiv
  • 17,306
  • 6
  • 61
  • 82
Maik Klein
  • 15,548
  • 27
  • 101
  • 197
  • What do you mean _'leaking'_? Did you simply miss proper include guards somewhere? – πάντα ῥεῖ Nov 19 '14 at 20:46
  • 1
    A good practice will be to include ALL of the required files in the main.cpp. – Eugene Sh. Nov 19 '14 at 20:46
  • Put in main what main needs. Keep files independent. Remember to add header guards in foo.h – Juan Leni Nov 19 '14 at 20:47
  • 2
    Each file should include the headers it needs, but this is tricky to maintain in practice, as files change and move around. It's just a quirk of C++ I've learned to live with. – Neil Kirk Nov 19 '14 at 20:48
  • 1
    Each module that uses a feature should include the relevant header. So main, which uses string will compile even if Foo no longer does. Header guards should prevent actual code from being included twice even if Foo and main both include string. You want Foo to be self-sufficient - main shouldn't have to include string for Foo. – emsr Nov 19 '14 at 20:48
  • Related question http://stackoverflow.com/q/26611481/3747990 – Niall Nov 19 '14 at 21:06

2 Answers2

4

No, there is no automated way to protect yourself from inadvertently relying on headers that you've included through other headers.

What you need to do is discipline yourself to include the relevant headers in each source file that uses them, even if each #include directive isn't strictly required in each source file.

The consequences of forgetting that aren't dire, though. If Foo.h eventually changes to no longer include string, then the code will fail to compile, but the fix is easy and takes almost no time. It's not worth worrying about.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
2

Let every file include only the dependencies it really needs. Also you should protect your own header files using include guards (C++ #include guards).

Foo.h:

#ifndef _INCLUDED_FOO_H_
#define _INCLUDED_FOO_H_ 

// Only #include <string> here if it is needed in the Foo.h
// ...
struct Foo;
// ...

#endif

main.cpp:

#include <string>
#include "Foo.h"
int main(int argc, char *argv[])
{
   std::string s = "hello";
}

This way main.cpp does still compile even if Foo.h changes later.

Community
  • 1
  • 1
MinusBrain
  • 96
  • 4