1

我使用术语“双链接”是因为我不知道实际的短语是什么,或者是否有一个,但假设您有两个标题,head1.h 和 head2.h,其中包含以下内容:

在 head1.h 中:

#include"head2.h"
//do stuff

在 head2.h 中:

#include"head1.h"
//do stuff

我把它想象成两个彼此相对放置的镜子,因为它并不是真正的无限循环,而是某种其他形式的无限进入有限的计算机(但我离题了)。关键是,在任何情况下使用这个概念或这个概念的变体是有用或必要的吗?(即:我想 goto 可以用作即兴休息)。

4

4 回答 4

7

通常,标头具有预处理器语句,以防止这种事情导致无限递归:

#ifndef MY_FILE_H
#define MY_FILE_H

//do stuff

#endif

即使有这种保护,相互包含通常也是一个坏主意。

于 2009-05-16T22:47:01.140 回答
3

这是一个“循环包含”,不,这不是一件可取的事情。你的 goto 不会有帮助,因为 goto 是程序执行的一部分,而 #includes 在编译的预处理阶段被解释。

通常的做法是使您的头文件具有类似的结构

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

所以他们不会尝试两次定义相同的东西。

如果您尝试一下,会发生以下情况:

bash $ gcc crecursive.c 在
从 bh.h:1 包含的文件中,

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

...省略了许多行

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

重击 $

于 2009-05-16T22:45:42.000 回答
1

避免这种情况的常用方法是使用空类声明。

//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); 
};

当一个头文件创建了许多需要在另一个之前声明的类时,您通常会得到一个包含文件,例如 .

//fwd.h

class Bar;
class Foo;

// head1.h

#include "fwd.h"

class Foo { ....

// head2.h

#include "fwd.h"

class Bar { ....
于 2009-05-16T22:48:43.787 回答
0

我把它想象成两个相互对置的镜子,因为它并不是一个无限循环

你想象错了。;) 请记住,#include 只不过是复制/粘贴,它发生在您的程序编译之前。所以你设置的是编译期间的无限循环。编译器读取head1.h,它以#include "head2.h" 开头。所以它插入了 head2.h 并继续解析它,但它以 #include "head1.h" 开头,所以我们必须包含它,依此类推。

你通常有包括警卫来防止编译器进入无限循环。

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.

于 2009-05-16T22:52:02.017 回答