循环#includes如何解决?

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

1.h #include blah blah 

我们有2.h.

 #include code 

这怎么解决?

通常,使用与文件名对应的ifndef / define保护include文件。 这不会阻止文件再次被包含,但它确实阻止了内容(在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 

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

你应该使用包含警戒:

 // header1.hpp #ifndef MYPROJECT_HEADER1_HPP_INCLUDED #define MYPROJECT_HEADER1_HPP_INCLUDED /// Put your stuff here #endif // MYPROJECT_HEADER1_HPP_INCLUDED 

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

  base.h / \ header1.h header2.h \ / class.cpp 

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

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

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

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

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

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

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

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

必须消除循环内含物,而不是用包括警卫“解决”(如接受的答案所示)。 考虑一下:

1.H:

 #ifndef HEADER_1_h #define HEADER_1_h #include "2.h" #define A 1 #define B 2 #endif // HEADER_1_h 

·H:

 #ifndef HEADER_2_h #define HEADER_2_h #include "1.h" #if (A == B) #error Impossible #endif #endif // HEADER_2_h 

main.c中:

 #include "1.h" 

这将在编译时抛出“不可能”错误,因为“2.h”由于包含保护而未能包含“1.h”,并且AB变为0.实际上,这导致难以跟踪错误根据包含头文件的顺序显示和消失。

这里正确的解决方案是将AB移动到“common.h”,然后可以包含在“1.h”和“2.h”中。

既然您在c ++标签和c下发布了您的问题,那么我假设您使用的是c ++。 在c ++中,您还可以使用#pragma once编译器指令:

1.H:

 #pragma once #include "2.h" /// rest of 1.h 

·H:

 #pragma once #include "1.h" /// rest of 2.h 

结果是一样的。 但有一些注意事项:

  1. pragma曾经通常会编译得更快,因为它是一个更高级别的机制,并且不会像包含警卫一样在预处理中发生

  2. 一些编译器已经知道错误“处理”#pragma一次。 虽然大多数(如果不是全部)现代编译器都能正确处理它。 有关详细列表,请参阅Wikipedia

编辑:我认为该指令在c编译器中也得到支持,但从未尝试过,而且,在我见过的大多数c程序中,包括防护是标准(可能是由于编译器限制处理pragma一次指令?)