包含防護提供了針對遞歸包含的保護,但它們無法防止相互包含的標頭中資料結構定義之間的依賴關係。考慮以下程式碼:
// header.h #ifndef HEADER_H #define HEADER_H class A; class B { public: A* pA; }; #endif // HEADER_H
// source1.cpp #include "header.h" A* aPtr = new A;
// source2.cpp #include "header.h" B* bPtr = new B;
在此場景中,source1.cpp 包含 header.h,而 header.h 包含 source2.cpp(間接)。這個行為可以透過 include Guard 來阻止,但是編譯器仍然會報錯,因為 header.h 中沒有定義類別 A。
要解決這個問題,可以在 header.h 中使用前向聲明:
// header.h #ifndef HEADER_H #define HEADER_H struct A; class B { public: A* pA; }; #endif // HEADER_H
這確保編譯器知道類 A 的存在,而無需提供其定義。
包含防護可防止同一翻譯單元(.cpp 檔案)內出現多個符號定義。但是,它們不能防止跨不同翻譯單元的多個定義。
考慮以下程式碼:
// header.h #ifndef HEADER_H #define HEADER_H int f() { return 0; } #endif // HEADER_H
// source1.cpp #include "header.h" int main() { f(); }
// source2.cpp #include "header.h" int main() { f(); }
在此範例中,函數 f()定義在 header.h 中。當 source1.cpp 和 source2.cpp 單獨編譯時,包含防護將防止每個翻譯單元內出現多個定義。然而,當目標程式碼連結在一起時,連結器會偵測到 f() 的多個定義。
要解決這個問題,可以使用inline 關鍵字告訴編譯器直接在函數定義處內聯調用站點:
// header.h #ifndef HEADER_H #define HEADER_H inline int f() { return 0; } #endif // HEADER_H
或者,可以將函數定義移動到單獨的.cpp文件中,以避免與其他翻譯單元中的定義發生衝突。
以上是為什麼 Include Guard 無法防止遞歸包含和多重符號定義?的詳細內容。更多資訊請關注PHP中文網其他相關文章!