我有几个头文件,归结为:
tree.h中:
#include "element.h" typedef struct tree_ { struct *tree_ first_child; struct *tree_ next_sibling; int tag; element *obj; .... } tree;
和element.h:
#include "tree.h" typedef struct element_ { tree *tree_parent; char *name; ... } element;
问题是它们都相互引用,因此树需要包含元素,元素需要包含树.
这不起作用,因为要定义"树"结构,元素结构必须已知,但要定义元素结构,必须知道树结构.
如何解决这些类型的循环(我认为这可能与'前向声明'有关?)?
我认为这里的问题不是缺少的包括警卫,而是这两个结构在他们的定义中需要彼此的事实.所以它是一种定义hann和egg问题的类型.
在C或C++中解决这些问题的方法是对类型进行前向声明.如果告诉编译器元素是某种结构,编译器就能生成指向它的指针.
例如
在tree.h里面:
// tell the compiler that element is a structure typedef: typedef struct element_ element; typedef struct tree_ tree; struct tree_ { tree *first_child; tree *next_sibling; int tag; // now you can declare pointers to the structure. element *obj; };
这样你就不必在tree.h中包含element.h了.
您还应该在头文件周围放置包含防护.
这里的关键观察是元素不需要知道树的结构,因为它只保存指向它的指针.树也一样.所有人都需要知道的是,存在一个具有相关名称的类型,而不是其中的内容.
所以在tree.h中,而不是:
#include "element.h"
做:
typedef struct element_ element;
这"声明"类型"element"和"struct element_"(表示它们存在),但不"定义"它们(说它们是什么).所有你需要存储一个指向blah的指针是声明blah,而不是它被定义.只有当你想要它(例如阅读成员)时,你才需要定义.".c"文件中的代码需要这样做,但在这种情况下,您的标题不需要.
有些人创建了一个单独的头文件,它在头部集群中正向声明所有类型,然后每个头包含它,而不是确定它真正需要哪些类型.这既不重要也不完全愚蠢.
关于包含警卫的答案是错误的 - 一般来说它们是个好主意,你应该阅读它们并让自己一些,但它们并不能解决你的问题.