C++ 由于嵌套而无法#包含,无法使用类原型

C++ 由于嵌套而无法#包含,无法使用类原型,c++,vector,header,include,C++,Vector,Header,Include,情境:我有一个粒子类和一个场类。粒子具有与其关联的场,反之亦然,场通常具有粒子 如果我在“particle.hpp”中包含“field.hpp”,我就不能在中包含“particle.hpp”。当然,这是有道理的 我在两个文件中都使用了前向声明,但是编译器现在无法编译,出现以下错误: error: invalid use of incomplete type ‘class ElementaryParticle’ error: forward declaration of ‘class Elemen

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

如果我在
“particle.hpp”
中包含“field.hpp”,我就不能在
中包含“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’
有解决这些问题的办法吗?我理解为什么会发生错误。如何定义这两个类而不将它们包含在其他文件中?这些问题的出现是因为场试图访问粒子的成员,而粒子包含一个场向量

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


编辑2:我知道标题保护。

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


另外,如果您不使用pragma,可能会有所帮助?

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


另外,如果您不使用pragma,可能会有所帮助?

大多数程序员在定义标题时使用include-guard。一些编译器允许

#pragma once
指令,但如果该指令不可用,通常的惯例是定义#ifndef防护装置,如下所示:

#ifndef PARTICLE_HPP__
#define PARTICLE_HPP__

class Field;

class Particle {
// ...
};

#endif // PARTICLE_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中,它可以同时包含两个头并具有两个对象的完整定义。只使用指针和引用使标题保持抽象,这样应该没问题。

大多数程序员在定义标题时使用include-guard。一些编译器允许

#pragma once
指令,但如果该指令不可用,通常的惯例是定义#ifndef防护装置,如下所示:

#ifndef PARTICLE_HPP__
#define PARTICLE_HPP__

class Field;

class Particle {
// ...
};

#endif // PARTICLE_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中,它可以同时包含两个头并具有两个对象的完整定义。只使用指针和引用保持标题的抽象性,这样就可以了。

字段中包含
粒子
,在
粒子
中包含
字段
,但在这两个标题周围都加上?我有点被你的问题弄糊涂了,但我认为这正是你想要的。“在每个标题中包含另一个标题”-这就是问题的确切原因。你可以使用标题防护装置来做到这一点。@Jesuplusplus Scott解释了解决方案。在
字段中包含
粒子
,在
粒子
中包含
字段
,但是在这两个标题周围都有?我有点被你的问题弄糊涂了,但我认为这正是你想要的。“在每个标题中包含另一个标题”-这就是问题的确切原因。你可以用标题保护来做到这一点。@Jesuplusplus Scott解释了解决方案。我为什么要使用pragma#once而不是#ifndef?这是相同的想法,只是更整洁而已。重要的问题是:为什么要在另一个标题中包含一个标题?在这种情况下,您可以通过回答“我不应该”来解决您的问题。通过正向引用声明您的依赖关系,然后在您的实现中定义它。@ScottMermelstein谢谢您的帮助,我会接受您的回答。@ScottMermelstein Fantastic mate,确实如此,干杯!没问题。为什么我要用pragma一次而不是ifndef?这是相同的想法,只是更整洁而已。重要的问题是:为什么要在另一个标题中包含一个标题?在这种情况下,您可以通过回答“我不应该”来解决您的问题。通过正向引用声明您的依赖关系,然后在您的实现中定义它。@ScottMermelstein谢谢您的帮助,我会接受您的回答。@ScottMermelstein Fantastic mate,确实如此,干杯!没问题。