【问题标题】:Double include solution?双包含解决方案?
【发布时间】:2011-12-01 17:29:19
【问题描述】:

在 C++ 中,我遇到了双重包含问题:

文件 stuffcollection.h

#pragma once
#ifndef STUFFCOLLECTION_H
#define STUFFCOLLECTION_H

#include "Stage.h"

class Stuffcollection {
    public:
        bool myfunc( Stage * stage );
};

#endif // STUFFCOLLECTION_H

文件stage.h:

#pragma once
#ifndef STAGE_H
#define STAGE_H

#include "Stuffcollection.h"

class Stage {
    // stuffcollection used in stage.cpp
};

#endif // STAGE_H

编译器错误:

\Stuffcollection.h|(line were bool myfunc is declared)|error: 'Stage' has not been declared| ||=== Build finished: 1 errors, 0 warnings ===|

有人能解释一下为什么会发生这种情况以及如何解决吗?我已经使用了包含警卫和 pragma once 预处理器指令,但它不起作用。

(如果我从 stage.h 中删除 #include "Stuffcollection.h" 并注释掉在 stage.cpp 中使用它的相应行,我的其余代码工作正常。实际上只是在将 Stuffcollection 包含到阶段时它突然停止工作.)

PS:stage 只是一个例子,我几乎在所有其他文件中都使用了 stuffcollection,每次遇到这个问题。

编辑:我遵循了建议,现在问题是invalid use of incomplete type,即虽然给出的答案解决了循环依赖的问题,但它们并没有解决我正在处理的问题.我的问题在Circular Dependencies / Incomplete Types 中继续存在。

编辑:现在都解决了。

【问题讨论】:

    标签: c++ include include-guards


    【解决方案1】:

    你有一个循环依赖。而是在 Stuffcollection.h

    中使用 Forward Declaration
    #pragma once
    #ifndef STUFFCOLLECTION_H
    #define STUFFCOLLECTION_H
    
    //#include "Stage.h"      //<------------------Don't Do This
    class Stage;              //<------------------Do This
    
    class Stuffcollection {
        public:
            bool myfunc( Stage * stage );
    };
    
    #endif // STUFFCOLLECTION_H
    

    理由:
    您可以在上面的 sn-p 中使用前向声明,因为 Stuffcollection.h 只使用指向 Stage 的指针。

    说明:
    使用类Stage 的前向声明,编译器不知道它的组成也不知道它里面的成员,编译器只知道Stage 是一个type。因此, Stage 是编译器的不完整类型。使用 Incomplete types ,人们不能创建它的对象或做任何需要编译器知道 Stage 的布局的事情,或者更多的是 Stage 只是一种类型。由于指向所有对象的指针只需要相同的内存分配,因此您可以在仅将Stage 引用为指针时使用前向声明。

    您可以使用前向声明来克服循环依赖问题。

    进一步阅读:
    When to use forward Declarations?

    【讨论】:

    • 我可能说得不够清楚,但我需要能够在阶段创建 stuffcollection 对象(或至少使用传入的 stuffcollection 对象的方法),反之亦然。现在我的问题是“不完整类型的无效使用”。
    • @Ben:你的 Q 实际上并没有提到它,你看链接了吗?它会给你一个完整的列表,列出你不能/不能用不完整的类型做什么。如果您有不完整类型的特定错误案例,请将其作为问题发布。
    • 抱歉,如果我不打算使用它,为什么还要包含它。无论如何感谢您的回答,我想这是解决循环依赖的方法,而不是特别针对我的问题。
    • @Ben:我想是的,可能,你只是混淆了两个问题,是的,这是循环依赖问题的解决方案。对于您的其他问题,请发布一个包含详细信息的新问题,以将两个不同的事情分开,并保证您有适当的解决方案。
    【解决方案2】:

    这是一个循环依赖。不要制造它们。您可以通过将 stuffcollection.h 中的 #include "Stage.h" 替换为 Stage 的前向声明(即 class Stage;)来解决这个问题。

    【讨论】:

    • 前两句中的合理建议值得 +1。
    【解决方案3】:

    您可以使用前向声明来代替#include,即class Stage;class Stuffcollection。它还具有减少依赖性的好处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 1970-01-01
      • 1970-01-01
      • 2013-09-05
      • 1970-01-01
      • 2017-08-29
      相关资源
      最近更新 更多