【问题标题】:Cannot #include due to nesting, cannot use class prototype由于嵌套不能#include,不能使用类原型
【发布时间】:2013-02-27 17:28:28
【问题描述】:

情况:我有一个 Particle 类和一个 Field 类。粒子具有与之关联的场,反之亦然,场通常具有粒子。

如果我在"particle.hpp"#include "field.hpp",我不能在"field.hpp"#include "particle.hpp"。当然,这很有道理。

我在这两个文件中都使用了前向声明,但是编译器现在无法编译并出现以下错误:

error: invalid use of incomplete type ‘class ElementaryParticle’
error: forward declaration of ‘class ElementaryParticle’

error: invalid use of incomplete type ‘class ElementaryField’
error: forward declaration of ‘class ElementaryField’

有没有办法解决这些问题?我明白为什么会发生错误。如何定义两个类而不将它们包含在彼此的文件中?这些问题的出现是因为场试图访问粒子的成员,而粒子包含场向量。

编辑:一种解决方法是将这些类合并到一个文件中的一个类中......但这很荒谬并导致各种其他问题。

EDIT2:我知道头卫。

【问题讨论】:

  • field 中包含particle,在particle 中包含field,但是用header guards 包围两个标题?我对你的问题有点困惑,但我认为这就是你想要的。
  • "在每个标头中包含另一个标头" - 这是问题的确切原因。
  • 你可以用头部保护来做到这一点。
  • @JesusPlusPlus Scott 解释了解决方案。

标签: c++ vector header include


【解决方案1】:

我会让 field.hpp 包含particle.hpp,在particle.hpp 中包含ElementaryField 的前向声明 - 然后在您的particle.cpp 中包含field.hpp。只要您在particle.hpp中没有任何代码,那应该可以解决您的问题。从技术上讲,您可以在 .hpp 中对每个进行前向声明,然后在 .cpp 中包含其他的 .hpp。这可能会更好,因为它更加标准化。我进行了最初的评估,因为你说场访问粒子的成员,而粒子只包含场向量。

另外,如果您不使用 pragma #once,也许会有所帮助?

【讨论】:

  • 为什么我应该使用 pragma #once 而不是 #ifndef ?
  • 思路一样,只是更整洁。重要的问题是:为什么要在另一个标题中包含一个标题?在这种情况下,您可以通过回答“我不应该”来解决您的问题。通过前向引用声明你的依赖,然后在你的实现中定义它。
  • @ScottMermelstein 感谢您的帮助,我会接受您的回答。
  • @ScottMermelstein 很棒的伙伴,确实如此,干杯!编译没问题。
【解决方案2】:

大多数程序员在定义头文件时都会使用包含保护。一些编译器允许

#pragma once

指令,但如果它不可用,通常的约定是定义 #ifndef 保护,如下所示:

#ifndef PARTICLE_HPP__
#define PARTICLE_HPP__

class Field;

class Particle {
// ...
};

#endif // PARTICLE_HPP__

#ifndef FIELD_HPP__
#define FIELD_HPP__

class Particle;

class Field {
// ...
};

#endif // FIELD_HPP__

完成后,您现在遇到了每个上下文中未定义类的问题。这里的解决方案是永远不要假设场中粒子的定义,永远不要假设粒子中的场定义。你有声明,这很好。但是不要使用任何需要定义的东西。例如,在 Particle.hpp 中,避免:

Field x;  // Error: Requires Constructor definition
Field *y; // Okay
Field &z; // Okay, but must be initialized in constructor
y->foo(); // Error: Requires definition of foo
z.bar;    // Error: Requires definition of bar

相反,将所有这些错误位放入您的 .cpp 中,该文件可以包含两个标头并具有两个对象的完整定义。只用指针和引用保持你的标题抽象,你应该没问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    相关资源
    最近更新 更多