【问题标题】:headers include and cyclic dependency标头包含和循环依赖
【发布时间】:2012-02-19 01:13:51
【问题描述】:

我想知道为什么下面的代码不起作用。 在b.cpp中,B类使用A类,但是因为找不到A类的声明而失败。 但是,a.hpp 就在之前包含在内。为什么#include "a.hpp" 在这里不起作用?

感谢您的帮助!

//===============================================
//file: a.hpp
//===============================================
#ifndef _A_HPP
#define _A_HPP

#include "b.hpp"

class A{
    public:
        A();
        // others methods using B here
};

#endif


//===============================================
//file: a.cpp
//===============================================
#include "a.hpp"

A::A(){}


//===============================================
//file: b.hpp
//===============================================
#ifndef _B_HPP
#define _B_HPP

#include "a.hpp"

class B{
    public:
        B(A a);
};

#endif
//===============================================
//file: b.cpp
//===============================================
#include "b.hpp"

B::B(A a){}



SHELL$ g++ -c a.cpp
In file included from a.hpp:7,
                 from a.cpp:4:
b.hpp:11: error: expected ‘)’ before ‘a’

【问题讨论】:

    标签: c++ header dependencies


    【解决方案1】:

    你需要使用Forward declarations来打破这种循环依赖。
    但是,请注意,一旦您转发声明一个类型,该类型就会成为编译器的不完整类型,并且对如何使用不完整类型有限制

    【讨论】:

      【解决方案2】:

      删除

      #include "b.hpp"
      

      来自 a.h 并且只有一个前向声明 - 假设您在 A 中使用指向 B 的指针:

      //A.hpp
      
      class B; //forward declaration
      
      class A{
          public:
              A();
              // others methods using B here
      };
      

      另外: 以下划线_ 开头的宏名称由标准保留,不应使用。将_B_HPP 替换为简单的B_HPP

      【讨论】:

        【解决方案3】:

        为什么需要这样的循环#include?如果您只需要编译器知道一个类的存在(所以它可以是一个参数等),只需像这样向前声明它:

        class A;
        

        不要循环包含文件。即使有警卫,它们也只会被包含一次,当然,但是你仍然会在编译器定义之前提到A,或者在编译器之前提到B得到它的定义。

        【讨论】:

        • 我认为#include 更好,因为它不会重复代码并使维护变得容易。但是好的,重复的代码只是“A类;”而且在真正的长源代码中应该不会更长...
        【解决方案4】:

        当b.hpp包含a.hpp时,_A_HPP已经定义了,所以预编译器会忽略文件的内容,所以在B(A a)这一行,编译器不知道A。

        如果您确实需要这些包含,请尝试将#include "b.hpp" 移动到a.hpp 的末尾(或在b.hpp 的头部声明class A;)。

        【讨论】:

        • 我以为一切都在一个大文件中,最后包含:a.cpp + a.hpp + b.hpp
        【解决方案5】:

        在 A.hpp 中,不要包含 B.hpp 或调用 B 方法的内联 A 实现。

        如果您需要引用B&B*,请在A.hpp 中使用class B;(前向声明)。

        相反,将那些调用 B 方法的 A 实现放在 A.cpp 中,并将 B.hpp 包含在 A.cpp 中。

        【讨论】:

          【解决方案6】:

          这行不通。在您的头文件中,您应该只包含指向其他类的引用或指针。然后你可以转发声明A或B,例如:

          //===============================================
          //file: b.hpp
          //===============================================
          #ifndef _B_HPP
          #define _B_HPP
          
          class A;
          
          class B{
              public:
                  B(A& a);
          };
          
          #endif
          

          【讨论】:

            猜你喜欢
            • 2011-03-23
            • 1970-01-01
            • 1970-01-01
            • 2012-06-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-09
            • 1970-01-01
            相关资源
            最近更新 更多