導言:
最近在看C++的編譯鏈接過程:編譯分爲預處理和彙編階段。預處理階段主要對宏進行處理1)將#include宏包含的文件整體拷貝過來;2)將#define定義的宏替換;3)根據條件宏#ifdef決定取捨那段代碼。
問題:
本來是想提一個問題的,可是寫着寫着就寫了一段代碼測試去了,測着測着,就想明白了。
我的原始問題是這樣的:假設有類A,頭文件A.h,實現文件A.cpp;還有一個B.cpp包含了A.h.在編譯B.cpp時,編譯器會發現A.h的頭文件保護宏已經定了(因爲A.cpp中也包含了A.h,假設A.cpp先於B.cpp定義),那麼B.cpp也就不會添加類A的定義代碼。這跟B.cpp不#include "A.h"有什麼區別呢?(顯然不#include "A.h"會報錯:未定義的標識符)。
當然我這個問題的描述就錯了,錯在我沒有弄明白源文件中宏的作用域僅限於當前文件。也就是說,B.cpp在編譯時會發現A.h的頭文件保護宏是沒有定義的,仍然會將類A的定義代碼直接拷貝過來。
總結:
1. 類的定義相當於聲明,聲明可以有多個,但定義只能有一個。這就是爲什麼類的定義文件不要有函數的實現的原因。
2. 頭文件保護是爲了防止同一個源文件多次包含該頭文件(會出現“類型重定義”的錯誤)。
3.我發現這樣也不會出錯:再寫一個文件AA.h,其中定義一個類A(名稱與之前的A一樣),但這個A的定義稍有不同。B.cpp包含AA.h。
4.那麼,A.cpp和B.cpp都包含了類A的定義,至於在連接階段爲什麼不會出錯,我還在思考,也許就是不會出錯。