我有两个类都在单独的头文件中定义。每个文件都有一个其他类的字段。现在我在每个文件的头文件中包含了其他文件的头文件,但是编译器正在生成错误。我错过了什么?
答案 0 :(得分:49)
你不能让每个班级都有“其他类型的字段”;这将是一个递归定义,不仅编译器无法理解它,它甚至没有逻辑意义。
每个具有另一个类型的字段的类是您在M.C.中看不到的那种不可能性。 Escher图纸或其动画,如下所示:
来源:escherdroste.math.leidenuniv.nl
基于埃舍尔的“印刷画廊”石版画,1956年,see Wikipedia
这两个字段中的一个必须是指针,以便打破递归包含,并避免逻辑上不可能。
这引出了下一个问题:如果B类要包含A类的实例,那么很明显,A必须在B类之前声明,因此在编译B时编译器已经知道A。但是如果类A在类B之前声明,我们如何在A中声明指向B的指针?在编译A时,B类还不知道!对此的答案是一个称为前向声明的特殊构造,它恰好存在以适应这种情况。 B类的前瞻声明如下:
class B;
所有这一切都告诉编译器会有一个名为B的类。它没有告诉编译器有关B类内容的任何信息,所以我们可以做的很少,但是我们可以做一件事:声明指向B的指针。
因此,问题的完整解决方案如下所示:
文件“A.h”:
/* This is called a "forward declaration". We use it to tell the compiler that the
identifier "B" will from now on stand for a class, and this class will be defined
later. We will not be able to make any use of "B" before it has been defined, but
we will at least be able to declare pointers to it. */
class B;
class A
{
/* We cannot have a field of type "B" here, because it has not been defined yet.
However, with the forward declaration we have told the compiler that "B" is a
class, so we can at least have a field which is a pointer to "B". */
B* pb;
}
文件“B.h”:
#include "A.h"
class B
{
/* the compiler now knows the size of "A", so we can have a field of type "A". */
A a;
}
答案 1 :(得分:20)
您不应将头文件包含在其他文件中,只需在源文件中包含头文件即可。
在标题中,您可以使用转发声明:
// In Class1.h
class Class2;
// In class2.h
class Class1;
此外,您还可以使用预处理器防止文件被包含两次:
// Class1.h
#ifndef __CLASS_1_H
#define __CLASS_1_H
// content
#endif
答案 2 :(得分:14)
我知道这是一个古老的话题,但也许你仍然对解决方案感兴趣!
实际上在C ++中,你可以在不使用指针的情况下递归使用两个类,这里是如何做到的。
文件:a.h
#include <b.h>
class A {
B<> b;
}
file:b.h
class A;
template<typename T = A>
class B {
T a;
}
file:main.cpp
#include "a.h"
A a;
就是这样!
当然这只是为了好奇:)
答案 3 :(得分:2)
您可能希望使用前向声明,除非您确实希望将每个类的实例放在彼此中。在这种情况下,你不应该使用任何东西。
答案 4 :(得分:0)
如果B只能存在于A内,我似乎可以在不使用指针的情况下创建A和B。 B必须简单地转发声明A而不包含它(避免递归包含)。
在我的情况下,一个Document
有一个Section
,它引用了它的Document
。
section.h
class Document;
class Section
{
public:
Section(Document& document) : document{document} {}
private:
Document& document;
};
document.h
#include "section.h"
class Document
{
public:
Document() : section{*this} {}
private:
Section section;
};
main.cpp
#include "document.h"
int main()
{
Document document{};
}
此代码使用g++
编译并在Linux上运行。
一组ifdef
(复杂)可能在其他情况下启用它,但是我不确定可读性...
答案 5 :(得分:0)
除了前向声明的可能性外,如果似乎彼此之间需要两个类,那么从我的经验来看,这是继承深度错误的信号。 确实,这些类是同级的,您应该为这两个都创建一个父类。 或者,您正在尝试使用实际上是父类的类,而该类应该与此父类具有同级。然后,您应该将此兄弟姐妹创建为第三类。