C 中相互包含的标头
在 C 中,有时需要标头相互包含。然而,这可能会导致问题,特别是当涉及到 #include 语句的放置位置时。
内部或外部宏
一般来说,#include 语句应该放置在宏内部,例如#ifndef include Guards。这可以防止编译期间无限递归,如以下示例所示:
// A.h
#ifndef A_H_
#define A_H_
#include "B.h"
class A {
private:
B b;
public:
A() : b(*this) {}
};
#endif // A_H_
// B.h
#ifndef B_H_
#define B_H_
#include "A.h"
class B {
private:
A& a;
public:
B(A& a) : a(a) {}
};
#endif // B_H_
将 #include 语句放在宏之外会导致编译器由于 A.h 和 B.h 之间的相互包含而无限递归。
未声明类型
但是,将 #include 语句放在宏内可能会导致未声明类型的问题。例如,考虑以下代码:
// A.h
#ifndef A_H_
#define A_H_
class A; // Forward declaration
#include "B.h"
class A {
private:
B b;
public:
A() : b(*this) {}
};
#endif // A_H_
// B.h
#ifndef B_H_
#define B_H_
#include "A.h"
class B {
private:
A a; // Directly include A
public:
B(A& a) : a(a) {}
};
#endif // B_H_
在这种情况下,编译器会抱怨 A 是 B.h 中未声明的类型。这是因为当包含 B.h 时,A.h 中的前向声明是不可见的。
解决方案:前向声明
要解决这些问题,最好使用前向声明并在必要时包含包含完整定义的标题。在这个例子中,A的前向声明应该添加到B.h中B的定义之前:
// B.h
#ifndef B_H_
#define B_H_
class A; // Forward declaration
#include "A.h"
class B {
private:
A a; // Directly include A
public:
B(A& a) : a(a) {}
};
#endif // B_H_
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3