C 头文件之间的循环依赖

Ste*_*eve 6 c header

有没有人有任何提示如何以系统方式处理大型程序中的符号常量和类型定义以避免头文件之间的循环依赖?我有一个想法,定义一个包含所有结构、联合和枚举类型定义的头文件和另一个包含所有符号常量定义的头文件。但是我对这个关于实现隐藏的解决方案有疑问。谢谢你的任何想法。

Chr*_*ner 6

您可以将typedef语句与实际struct定义分开,并将它们放在包含其他标题之前。这样,如果您的数据类型foo包含 type 的成员bar *,则它不需要立即定义bar- 知道它是稍后将得到解析的有效数据类型会很高兴。

#ifndef FOO_H
#define FOO_H

typedef struct foo_s foo;

#include "bar.h"

struct foo_s
  {
  bar *my_bar;
  };
#endif
Run Code Online (Sandbox Code Playgroud)

.

#ifndef BAR_H
#define BAR_H

typedef struct bar_s bar;

#include "foo.h"

struct bar_s
  {
  foo *my_foo;
  };
#endif
Run Code Online (Sandbox Code Playgroud)

  • 好的。假设您有一个“人”结构,其中包括他们居住的“房子”。该“房子”结构还有一个住在房子里的“人”列表。如果这些链接中的任何一个被遗漏,您需要搜索每个“人”或“房子”以找到丢失的反向连接。 (3认同)
  • 将两个结构互连的原因有很多 - 您将如何处理?你愿意把它们放在同一个头文件中吗? (2认同)
  • @Lundin 这只是我提出的一个可能的例子。我相信有很多原因可以解释为什么你可能有一个没有“房子”上下文的“人”——也许你可以搜索一个“人”来找出他们住在哪里?迭代每个“房子”然后每个“房子”中的每个“人”以找出某人住在哪里似乎比将“房子”作为“人”的属性更糟糕的设计 (2认同)

Lun*_*din 4

解决方案是简单地使用某种程序设计方式。程序中的每个“对象”/“模块”应包含一个 h 文件和一个 c 文件。h 文件是公共接口。每个这样的对象应该只关心它自己指定的任务。它应该只包括执行该任务所需的资源。

通过这样的设计,决不应该存在任何循环依赖,否则设计就有缺陷。你不应该用各种代码技巧来修复糟糕的设计,你应该重新设计。

但当然,同一资源可以从代码的不同部分多次包含。这就是为什么我们总是在每个 h 文件中使用标头保护。

  • 一个例子在这里会有帮助:P (3认同)
  • 循环依赖对您来说不是一个有效的设计?没有任何需要循环依赖的用例吗?我认为这种推理是相当有偏见的。确实,一些循环礼仪可能有糟糕的设计,但这个概念本身并没有缺陷。 (2认同)