C++头文件包含

3
我正在处理一个项目,每个头文件都有一个预处理器包含守卫。我的包含方式如下:
(文件->包含)
main.cpp -> header.h; Character.h
header.h -> vector, iostream, ... , DataFiles.h
Character.h -> DataFiles.h,header.h,CharFrame.h
CharFrame.h -> DataFiles.h,header.h
一切都工作得很好。但是如果我只删除 main.cpp 的 #include "Character.h" 并将其移动到 header.h 中,编译时会出现很多错误。所以现在是这样的:
main.cpp -> header.h
header.h -> ... , DataFiles.h, Character.h.
有什么区别?
以下是我的编译器输出:
Inspiron-1545:~/Desktop/LF2_linux$ g++ -Wall main.cpp DataFiles.cpp header.cpp Character.cpp CharFrame.cpp -lSDL -lSDL_image -lSDL_ttf -o test
In file included from header.h:13:0,
             from CharFrame.h:12,
             from CharFrame.cpp:1:
Character.h:55:15: error: ‘CharFrame’ was not declared in this scope
Character.h:55:25: error: template argument 1 is invalid
Character.h:55:25: error: template argument 2 is invalid

如果将include放回到main.cpp中,则可以编译而不会出现任何错误。

如果您认为我的代码是必要的,我会编辑此帖并粘贴所有内容。

以下是需要关注的行:

header.h:13 ->
 #include "Character.h"
CharFrame.h:12 -> 
 #include "header.h"
CharFrame.cpp:1 -> 
 #include "CharFrame.h"
Character.h:55 ->  
 std::vector <CharFrame*> *frame;

听起来 header.h 使用了 CharFrame,但是它在 CharFrame.h 中声明之前就已经被包含(使用)了。因此编译器在 CharFrame 被声明之前就遇到了它。 - Violet Giraffe
如果你正在做你所说的事情,那么就不应该有任何区别。但出于某种原因,编译器无法识别类型“CharFrame”。你能否发布一个SSCE来重现这个问题? - Mahesh
我认为你不能直接包含两个头文件(header.h,charframe.h)。如果存在循环依赖关系,可以使用多种解决方案之一。 - khajvah
@Violet Giraffe:我认为你找到了问题,每个文件都包含其他文件...有没有办法绕过这个问题,或者我必须从头重新思考我的代码结构? - Alexandre Toqué
1
@AlexandreToqué,这篇文章建议使用前向声明来解决循环依赖问题。在header.h中进行charframe类的前向声明,在header.cpp中进行实现。 - khajvah
显示剩余5条评论
1个回答

5

您的更改在Character.h和header.h之间创建了一个包含循环。

可以推断,Character.h依赖于headers.h中的某些声明。现在,随着您的更改,以下情况发生:

  1. 头文件headers.h被包含,并定义了其包含保护,预处理器开始检查其内容。

  2. headers.h在进行自己的声明之前,先包含Character.h。

    1. Character.h定义了其包含保护,预处理器读取其内容。

    2. Character.h包含header.h以获取其所需的定义。

      1. 然而,headers.h看到了它的包含保护,并被解析为空。此时没有进行任何定义。
    3. 读取Character.h的定义。

  3. 读取headers.h的定义。

正如您所见,Character.h中的定义在其所依赖的header.h中的定义之前被读取。

修复循环包含的最佳方法是尽可能使用前向声明替换#include语句。在一些罕见的情况下,可能需要实际混合声明和包含,但应尽量避免这样做。


谢谢,这样就完成了khajvah链接中的解释,其中示例将#include放在不应该放置的位置,正如您刚才所说的 :) - Alexandre Toqué

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接