循环#includes如何解决?

Laz*_*Laz 3 c c++

在c中假设我们有2个文件

1.h

#include<2.h>

blah blah
Run Code Online (Sandbox Code Playgroud)

我们有2.h.

#include<1.h>

code
Run Code Online (Sandbox Code Playgroud)

这怎么解决?

tva*_*son 16

通常,使用与文件名对应的ifndef/define保护包含文件.这不会阻止文件再次被包含,但它确实阻止了内容(在ifndef中)被使用并再次触发递归包含.

 #ifndef HEADER_1_h
 #define HEADER_1_h

 #include "2.h"

 /// rest of 1.h

 #endif

 #ifndef HEADER_2_h
 #define HEADER_2_h

 #include "1.h"

 //  rest of 2.h

 #endif
Run Code Online (Sandbox Code Playgroud)

  • 虽然你不应该用`__`开始包含警戒名称.这样的名字是保留的. (3认同)

Mat*_* M. 7

好的,为了完整起见,我将首先引用tvanfosson的回答:

你应该使用包含警戒:

// header1.hpp
#ifndef MYPROJECT_HEADER1_HPP_INCLUDED
#define MYPROJECT_HEADER1_HPP_INCLUDED

/// Put your stuff here

#endif // MYPROJECT_HEADER1_HPP_INCLUDED
Run Code Online (Sandbox Code Playgroud)

但是,包含防护并不意味着解决循环依赖问题,它们旨在防止多个包含,这是完全不同的.

          base.h
        /        \
    header1.h  header2.h
        \        /
         class.cpp
Run Code Online (Sandbox Code Playgroud)

在这种情况下(很常见),你只需要将base.h包含一次,这就是包含警卫的内容.

所以这将有效地防止双重包含... 但你将无法编译!

可以通过尝试推理编译器来解释这个问题:

  • 包括"header1.hpp">这定义了包含守卫
  • 包括"header2.hpp
  • 尝试包含"header1.hpp"但不包括因为已经定义了包含保护
  • 无法正确解析"header2.hpp",因为来自"header1.hpp"的类型尚未定义(因为它被跳过)
  • 回到"header1.hpp","header2.hpp"中的类型仍然缺失,因为它们无法编译,因此它也失败了

最后,你会留下一大堆错误消息,但至少编译器不会崩溃.

解决方案是以某种方式消除对此循环依赖的需要.

  • 如果可能,使用前向声明
  • 将"header1.h"分成两部分:独立于header2的部分和另一部分,你应该只需要在header2中包含前者

而且这将解决循环依赖(手动)编译器中没有任何魔法可以为你做.