views:

124

answers:

4

I use the term "double link" because I don't know what the actual phrase is, or if there is one, but assuming you have two headers, head1.h and head2.h, with these contents:

In head1.h:

#include"head2.h"
//do stuff

In head2.h:

#include"head1.h"
//do stuff

I visualise it as two mirrors placed opposite each other, as it's not really an infinite loop, but some other form of getting infinity into a finite computer (but I digress). The point is, is there any situation where it would be useful or necessary to use this concept, or a variation of this concept? (ie: I suppose goto could be used as an improv break).

+3  A: 

That's a "cyclic include" and no, it's not a desirable thing to do. your goto wouldn't help, because gotos are part of the program execution, while the #includes are interpreted during the preprocessing phase of compiling.

The usual thing is to make your header files have a structure like

#ifndef FOO_H
#define FOO_H
... rest of the include file here
#endif

so they don't attempt to define the same stuff twice.

Should you try it, here's what happens:

bash $ gcc crecursive.c In file
included from bh.h:1,

            from ah.h:1,  
            from bh.h:1,  
            from ah.h:1,

... many lines omitted

            from ah.h:1,   
            from crecursive.c:2: ah.h:1:16: error: #include nested too deeply

bash $

Charlie Martin
+7  A: 

Usually, headers have preprocessor statements to prevent precisely this kind of thing from causing an infinite recursion:

#ifndef MY_FILE_H
#define MY_FILE_H

//do stuff

#endif

Even with that protection, mutual includes are usually a bad idea.

kdt
OTOH, a minor variation is common - head1.h includes head3.h (because it needs the services of head3.h), and so does head2.h, and code that includes both head1.h and head2.h needs to be protected from including head3.h twice. The header guards shown prevent that from causing trouble.
Jonathan Leffler
+1  A: 

The usual way to avoid this is with empty class declarations.

//head1.h

class Foo;

class Bar {
public:
   Bar(Foo* f) : foo(f) {}
private:
   Foo* foo;
};

// head2.h

class Bar;

class Foo {
public:
    void func(Bar* bar); 
};

When a header file creates a lot of classes that need to be declared before one another you usually end up with an include file like .

//fwd.h

class Bar;
class Foo;

// head1.h

#include "fwd.h"

class Foo { ....

// head2.h

#include "fwd.h"

class Bar { ....
jmucchiello
"Empty class" declarations are actually called forward declarations FYI
njsf
A: 

I visualise it as two mirros placed opposie each other, as it's not really an infinite loop

You visualize wrong. ;) Keep in mind that #include is nothing more than copy/paste, and it happens before your program is compiled. So what you've set up is an infinite loop during compilation. The compiler reads head1.h, which starts with #include "head2.h". So it inserts head2.h and continues parsing that, but it starts with #include "head1.h", so we have to include that, and so on.

You usually have include guards to prevent this from putting the compiler into an infinite loop.

The key is that this happens as plain text processing before the program is compiled, and certainly before it is executed, so it's not really something you can use for anything constructive, unless copy/pasting an infinite number of times is your idea of a fun time.

jalf