tags:

views:

160

answers:

7

Assuming that all headers are guarded, let's say you had an abstract data type.

#include "that.h"
#include "there.h"

class Foo {
 protected:
  // Functions that do stuff with varOne and varTwo
 private:
  that varOne; 
  there varTwo;
 ...
};

Then in the classes that inherit from foo ( and thus include foo.h ), would you also bother including that and this? Normally what I do is include everything that a class needs, regardless of whether would already receive them from another include. Is this redundant?

A: 

Yes it is. Include statements are replaced with the actual source from those files. If you have them more than once you have the code more than once.

apphacker
He stated in his first sentence that all the headers are guarded, so the code will *not* be included more than once.
Peter Alexander
Poita, you are wrong. Each obj file will get all the code from all the headers it includes. So including unnecessary headers leads to bloated code size.
Charles Eli Cheese
No. Include guards prevent against this. Think of it like once a header has been included once in a file, the include guard goes up. Even if that header is included again, it won't "re-get" the code from the header because the guard is up. So you could have 1 inclusion of a single header or 20, and there wouldn't be a difference performance wise.
Anonymous
Antiguru, header files do not generate code (excluding inlines), they are purely a compile time construct to let the compiler know the signature of functions and the layout of classes.
Peter Alexander
Isn't "Antiguru" a trollish name, anyway? I think what he may be saying is that, if you include headers you don't need, it may generate code for some classes if the compiler decides not to inline them. Of course, this issue is outside the scope of the main question.
Seth Johnson
A: 

It's up to you really. If it's plainly obvious that the super class has included them (i.e. without looking at its header) then it would make sense to omit the #include. Of course, you are free to add them just to be safe.

Peter Alexander
Alright thanks. I didn't figure it was a big deal, just kind of interested if there were any valid arguments against it. Looks like there aren't.
Anonymous
A: 

It's not necessarily redundant. The fact that you have separate header files and source files means that you can swap src and header files around as long as the source files provide definitions for the header files.

The .h file should include only things that are used in the header. It doesn't need stdio for example if there are no io declarations in the header, instead it should only go in the src file if it is using printf for example.

But there might be situations where one header you can use will need a particular include, while another header won't (e.g. when one header is a more restrictive interface than the other), in which case it's better to duplicate the .h includes.

Since it's guarded, it really makes no difference to the final object/exe you produce, and it doesn't increase compile time by anything worth worrying about, so it's better to include them just in case you want to use a different .h file at some point.

edit: more concrete example inc1.h

#ifndef INC1_H
#define INC1_H
inc1_struct {                                                            
   int x;
};
#endif

inc2.h

#ifndef INC2_H
#define INC2_H
#include "inc1.h"
void inc2_f();
struct inc1_struct *inc2_callinc1();
#endif

prog.cpp #include "inc1.h" #include "inc2.h"
#include #include

void inc2_f() {
   printf("inc2_f\n");
}

struct inc1_struct *inc2_callinc1() {
   return (struct inc1_struct*) malloc(sizeof(struct inc1_struct));
}

int main(int argc, char **argv) {
   struct inc1_struct *s = inc2_callinc1();
   return 0;
}

This would compile, but lets say you don't want to expose

struct inc1_struct *inc2_callinc1();

in inc2.h

Then you won't need to include inc1.h in the inc2.h file, but if you don't want to also delete the definition of inc2_callinc1() in prog.cpp, then you need to have included inc1.h.

Charles Ma
+1  A: 

In my experience, it's better to forward declare there and that in Foo.h rather than include them at all, since they are not technically needed given that they are passed by reference.

In that cade, Foo.h would look like:

class that;
class there;

class Foo
{
    public:

        void func( that &param ) = 0;
        void funcTwo( there &param ) = 0;
        ...
};
Don Neufeld
Thanks. Dumb mistake, I'll make the example a bit more realistic.
Anonymous
+1  A: 

Then in the classes that inherit from foo ( and thus include foo.h ), would you also bother including that and this?

Typically I'll include headers (with guards) for any types the header uses directly.

However, I often drop that for a derived class where the base class must have included them because of member function prototypes that are overridden -- which is true for this and that in your example.

Ultimately it's your choice, but you may also consider how likely you think the headers are to ever change - since that's the only time it really matters.

NVRAM
+1  A: 

The problem is that you end up including extra things in your obj files this way. The header guards don't prevent this. Anything you reference must be in your object, so don't just have lots of headers including other headers then include that elsewhere. If you are sloppy with your headers and have many files you quickly get a bloated code size and slow compile time.

Charles Eli Cheese
+2  A: 

There is one downside to redundantly including header files that would otherwise have been included directly: it forces the compiler to reopen and reparse them. For example, in

a.h:

#ifndef __A_H
#define __A_H
// whatever
#endif

b.h:

#ifndef __B_H
#define __B_H
#include "a.h"
// whatever
#endif

c.cpp:

#include "a.h"
#include "b.h"
//whatever

a.h has to be opened and read twice -- although the #ifndef will make the preproc ignore a.h's contents in the second inclusion, it still has to at least load the file from disk and read its bytes from the #ifndef to the #endif.

This can slow down compilation. It will not break your build or anything though, it'll just be an annoyance in really large projects, where compiles can take many minutes.

If you use #pragma once in your headers, there's a good chance an aware compiler will cache the filenames at a higher level, and ignore the second inclusion of a.h altogether. That too can speed up builds.

Crashworks
Thanks. I considered this, but didn't think that the reading of that would slow down compilation significantly.
Anonymous
I have heard (http://www.efnetcpp.org/wiki/Include_guards) that gcc and other compilers may cache the header files and automatically recognize include guards. The performance penalty for this is likely negligible.
Seth Johnson
It depends on the size of the project. For something that takes two minutes to compile, you won't notice a difference. For us, we go on an annual #include-dependency-spring-cleaning that typically shaves 5-10 minutes off of a 30 minute rebuild. I've heard that some people even take this one step further -- rather than having, say, 300 .cpp files that get compiled and then linked, they have 6 .cpp files each of which #includes 50 others, so the compiler deals with fewer units. They've said it's as much as halved their compile times, but in our case it blew out the compiler's memory!
Crashworks
Seth: that's what #pragma once does (tells the compiler to cache the headers) -- none of the compilers that I know of are smart enough to do it just based on the #ifndef, although of course the OS will cache disk as much as it can.
Crashworks
I think the issue you're talking about and the original question are different. Removing *unnecessary* headers definitely reduces build time, since your compiler doesn't have to parse and recurse through all that extra code. However, the original question seems to address whether *relying* on a header's includes is okay, or if it is better to add an explicit include if your working file needs that header's contents.
Seth Johnson
It's the same issue: is it okay to redundantly include headers that are themselves included from other headers? The answer is a tradeoff: re-including a.h from c.cpp even though it came in from b.h makes you safer from accidental build breakages when stuff gets shuffled around between headers or objects, and it also slows down builds. You just need to balance whether you care about safety or speed more.
Crashworks
After researching it for a bit, I read that GCC ( the compiler I use ) is smart enough to cache headers based on #ifndef. http://en.wikipedia.org/wiki/Pragma_once
Anonymous