場景
// main.cpp
#include "a.h"
// a.cpp
#include "a.h" // 為什麼這裡也要包含?
// a.h
#ifndef A_H
#define A_H
// 聲明...
#endif
核心解釋
- 宏全局唯一:
A_H 在**整個編譯單元 (Translation Unit) 範圍內**唯一。預處理器按文件順序展開,#ifndef A_H 確保頭文件內容**每個 .cpp 編譯單元中只展開一次**。
- 為什麼 a.cpp 必須包含 a.h?
- a.cpp 實現 a.h 中聲明的函數/類,**需要知道完整定義**(類佈局、成員類型、內聯函數體、模板實現等)。
- 若不包含,編譯器看到
void A::func() { ... } 時不知道 A 的結構,報錯「未定義類型」。
- 即使 main.cpp 已包含,編譯單元是**獨立**的,a.cpp 編譯時看不到 main.cpp 的內容。
- 防重複包含作用:防止同一 .cpp 中多次
#include "a.h" (直接或間接) 導致重複定義錯誤。
編譯流程圖解
main.cpp -----------------------> main.obj
#include "a.h" (展開聲明)
// 使用 A 類
a.cpp --------------------------> a.obj
#include "a.h" (展開聲明,宏 A_H 已定義但本單元首次見到,仍展開)
// 實現 A 類方法
鏈接器: main.obj + a.obj --> executable
現代 C++ 建議
- 使用
#pragma once 替代宏防衛(編譯器支持普遍,更簡潔)。
- 頭文件僅放聲明,實現放 .cpp (模板除外)。
- 模塊化 (C++20 Modules) 將徹底替代頭文件包含機制。