3

我检查了 SO 是否有重复项,但无法为我的问题找到确切的解决方案。

我有一个NvCommon.h使用 enum的头文件NV_DATA_TYPE。这个枚举是在另一个头文件中定义的NvDefs.h,我在其中使用了来自NvCommon.h. 由于循环依赖,我无法构建它。我知道转发声明枚举是不可能的。

在这种情况下可以做些什么?这是我设计的问题吗?我是否必须引入另一个头文件来解决这个问题?

我不是 C 专家。请帮我。我的设计可能有问题,我知道可以通过引入另一个头文件来修复这种循环依赖。我想知道的是“这是唯一的方法”。寻找替代解决方案(如果有)。

如果有帮助,我会发布完整的代码。

4

5 回答 5

10

在他们自己的文件中定义枚举可能很有用,如果你在这里这样做,你的问题就会消失。

于 2013-02-19T13:18:37.537 回答
6

如果我正确理解了您的问题,您将得到如下信息:

derpfoo.h:

#ifndef DERPFOO_H
#define DERPFOO_H

#include "derpbar.h"

typedef struct {
        char *nothing;
} FOO;

BAR foo (BAR derp) {
        return derp;
}

#endif

derpbar.h:

#ifndef DERPBAR_H
#define DERPBAR_H

#include "derpfoo.h"

typedef struct {
        char *nothing;
} BAR;

FOO bar (FOO derp) {
        return derp;
}

#endif

然后是一个简单的derp.c:

#include "derpfoo.h"
#include "derpbar.h"

int main (void) {
        return 0;
}

我的一个朋友不久前在一些 SDL 代码中向我提出了这个问题,我花了一段时间才理解他为什么要这样做以及如何合理地解决它。

像这样分离代码的目的是 derpfoo 和 derpbar 在逻辑上是分开的,但遗憾的是,它们也是相互依赖的。我发现的最简单的解决方案是将它们组合起来并根据解剖结构而不是像这样的逻辑来拆分它们:

derpstructs.h:

#ifndef DERPSTRUCTS_H
#define DERPSTRUCTS_H

typedef struct {
        char *nothing;
} FOO;

typedef struct {
        char *nothing;
} BAR;

#include "derpfunctions.h"

#endif

derpfunctions.h:

#ifndef DERPFUNCTIONS_H
#define DERPFUNCTIONS_H

#include "derpstructs.h"

BAR foo (BAR derp) {
        return derp;
}

FOO bar (FOO derp) {
        return derp;
}

#endif

仍然是一个简单的derp.c:

#include "derpstructs.h"
#include "derpfunctions.h"

int main (void) {
        return 0;
}

请注意,derpstructs.h在末尾而不是开头包含 derpfunctions.h。严格来说,这不是必需的,但如果您确实打算让它们相互包含,则必须在所有可能的包含路径中包含它们所依赖的结构定义之后的函数定义。继续...

这个解决方案有效,但它并没有完全坚持导致问题开始的原始哲学——这两个部分在逻辑上是分开的,并且应该在代码中保持这种状态。

两者的答案是进一步拆分所有内容,并进一步调整包含路径。

derpfoostructs.h首先包含 derpbarstructs.h ,然后定义 struct FOO,最后可选地包含 derpfoofunctions.h 和 derpbarfunctions.h。

derpbarstructs.h首先包含 derpfoostructs.h ,然后定义 struct BAR,最后可选包含 derpfoofunctions.h 和 derpbarfunctions.h。

derpfoofunctions.h首先包含derpfoostructs.h和derpbarstructs.h 然后包含derpbarfunctions.h,然后定义其函数。

derpbarfunctions.h首先包含derpfoostructs.h和derpbarstructs.h 然后包含derpfoofunctions.h,然后定义其函数。

derp.c 包括derpfoostructs.h 和derpbarstructs.h ,然后包括derpfoofunctions.h 和derpbarfunctions.h,然后继续做它需要做的任何其他事情。

这满足了两个期望的要求。它消除了循环依赖,并且仍然保持两个逻辑分离的代码单元的逻辑分离。当您从一个项目更改为另一个项目时,您需要编辑两个文件而不是一个,但它至少使可变代码与不可变代码分开。那是我找到的唯一解决方案。

希望这有帮助。祝你的项目好运。

于 2013-02-27T09:24:02.367 回答
2

循环依赖可能意味着你过度设计了你的界面。将两个文件合并到 Nv.h 中。如果这可以轻松解决问题,则意味着您错误地设计了界面。

于 2013-02-26T03:50:18.603 回答
1

我尝试根据您的描述对这个问题进行建模。在我的实现中,我测试了三件事(1)在 NvDefs.h 中声明但未定义 NV_DATA_TYPE,(2)在 NvDefs.h 中声明和定义 NV_DATA_TYPE,以及(3)在 NvDefs.h 中定义 NV_DATA_TYPE,但将其声明为 NvCommon.h . 此外,正如您提供的描述,我在 NvCommon.h 中创建了一些结构并在 NvDefs.h 中访问了这些对象。在每种情况下——无论在头文件中是否有保护——编译和执行的代码都是正确的结果。

除了 NV_DATA_TYPE 枚举之外,您的循环依赖项是否可能位于头文件中的其他位置?

于 2013-02-27T04:42:01.200 回答
1

看一下这个

如何正确声明和定义变量、库、函数等。这可能是相关的。

于 2013-02-26T21:30:52.510 回答