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