代码之家  ›  专栏  ›  技术社区  ›  Laz

循环包含是如何解决的?

c c++
  •  3
  • Laz  · 技术社区  · 14 年前

    在c中,假设我们有两个文件

    1.h
    
    #include<2.h>
    
    blah blah
    

    我们有 2.小时

    #include<1.h>
    
    code
    

    这是怎么解决的??

    4 回复  |  直到 14 年前
        1
  •  16
  •   tvanfosson    14 年前

    通常使用与文件名对应的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
    
        2
  •  8
  •   Matthieu M.    14 年前

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

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

    然而,include-guards并不是用来解决循环依赖问题的,它们是用来防止多个包含的,这是完全不同的。

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

    所以这将有效地防止双重夹杂。。。

    • 包括“header1.hpp”>这定义了包含保护
    • 包括“header2.hpp
    • 无法正确分析“header2.hpp”,因为来自“header1.hpp”的类型尚未定义(因为它被跳过)
    • 回到“header1.hpp”,来自“header2.hpp”的类型仍然丢失,因为它们无法编译,因此在这里也失败了

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

    • 如果可能,请使用转发声明
    • 将“header1.h”拆分为两部分:独立于header2的部分和另一部分,您只需要将前者包含在header2中

        3
  •  0
  •   eladidan    14 年前

    既然你把你的问题贴在了c++标签和c下,那么我假设你使用的是c++。在c++中,还可以使用 #pragma一次 编译器指令:

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

    2.小时:

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

    1. pragma once通常会编译得快一点,因为它是一种更高级的机制,不像include guards那样在预处理时发生

    2. 有些编译器曾经遇到过“处理”pragma的bug。尽管大多数现代编译器都能正确处理它。有关详细列表,请参阅 Wikipedia

    Edit:我认为c编译器也支持这个指令,但从未尝试过,而且,在我见过的大多数c程序中,include-guard是标准的(可能是由于编译器在处理pragma-once指令时的限制?)

        4
  •  0
  •   Dmitry Grigoryev    7 年前

    圆形夹杂物必须 消除

    1.小时:

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

    2.小时:

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

    主c:

    #include "1.h"
    

    这将在编译时抛出“不可能”错误,因为“2.h”由于包含保护而未能包含“1.h”,并且两者都包含 A B 实际上,这会导致难以跟踪错误,这些错误的出现和消失取决于头文件的包含顺序。

    A 到“common.h”,然后可以包含在“1.h”和“2.h”中。