【发布时间】:2018-02-07 02:01:41
【问题描述】:
假设我有一个 A 类和一个 B 类以及它们对应的标题:
啊。
#ifndef CLASS_A
#define CLASS_A
/* forward declare A */
class A;
/* includes */
#include "b.h"
/* define class A */
class A {
public:
A() : p_b(nullptr) {}
B *p_b;
};
#endif
b.h
#ifndef CLASS_B
#define CLASS_B
/* forward declare B */
class B;
/* includes */
#include "a.h"
/* define class B */
class B {
public:
B() : m_a() {}
A m_a;
};
#endif
这不起作用:
为了将 A 的实现编译成一个目标文件,我首先包含 ah,它转发声明 A,然后包含 bh,然后声明和定义 B。但是当 B 被定义时,它不知道 A 的大小,因此不能将 A 的对象声明为 B 的成员。
然而,A 不需要知道 B 的大小,因为它只有一个指向 B 的指针,并且可以在定义 B 之前完全定义。因此,在将 B 用作成员之前,可以完全知道 B 的大小,并且完整的声明应该没问题。
常识告诉 a.c 文件应始终如下所示:
#include "a.h"
[...]
我可以通过在 a.c 中包含 a.h 之前的 b.h 来实际解决问题吗?这是否违反了将实现文件的第一行包含在其标头中的某些神圣约定?
【问题讨论】:
-
你有没有想过在定义A之后包含b.h?
-
那么 A 会失败,因为 B 在我创建指向它的指针时不会定义类型,我认为。
-
通常,您在需要它们的文件中提出声明,而不是让标头本身包含使用第一个标头的不同标头。
-
您想使用前向声明来消除 a.h 和 b.h 之间的循环依赖。删除 a.h 中 b.h 的包含,并将 A 的前向声明替换为 B 的前向声明。在其自己的标头中前向声明一个类是没有意义的(除非您有一个复杂的标头)。
-
非常好的阅读,如果不是完全重复的话:Resolve build errors due to circular dependency amongst classes
标签: c++ member forward-declaration