头包括和循环依赖关系

headers include and cyclic dependency

本文关键字:依赖 关系 循环 包括      更新时间:2023-10-16

我想知道为什么下面的代码不起作用。在b.cpp中,类b使用类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’

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

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

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

删除

#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

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

class A;

不要循环包含文件。即使有了保护,它们也只会被包含一次,当然,但在编译器到达其定义之前,你仍然会遇到A的提及,或者在编译器到达定义之前遇到B的提及。

当b.hpp包含a.hpp时,已经定义了_A_HPP,因此预编译器忽略文件的内容,因此在B(A a)行中,编译器不知道a.

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

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

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

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