Context
- 在HeaderFile.h頭文件了聲明一個 LOG() 方法
void LOG(std::string s) { std::cout << s << std::endl; }
- 在SourceFile1.cpp裏 #include “HeaderFile.h”
- 在SourceFile2.cpp裏 #include “HeaderFile.h”
編譯報錯, a方法 duplicate symbol
實際報錯的log
上文的Context只是說明關係,swapElement就等於上文的a方法, MergeSort.cpp TestSort.cpp等價於SourFile1.cpp、SourceFile2.cpp
clang++ MergeSort.cpp TestSort.cpp -o testExecute
duplicate symbol __Z11swapElementPiii in:
/var/folders/wv/16gvb9rd4v540qx_6vry7vqh0000gn/T/MergeSort-dd8696.o
/var/folders/wv/16gvb9rd4v540qx_6vry7vqh0000gn/T/TestSort-0defcb.o
原因
- C++,方法不能被重複聲明。
- 編譯階段:#include “HeaderFile.h”,等於複製 HeaderFile.h 文件內容到 #include的位置。
- 編譯輸出:每個cpp文件被編譯成.o文件,所以MergeSort.o,TestSort.o文件內,都copy了HeaderFile.h內的內容(即方法聲明)
- 鏈接(Link)階段:鏈接每個.o文件成爲最終的 可執行文件。鏈接MergeSort.o,TestSort.o,出現兩個方法聲明,異常報錯 duplicate symbol
3種解決方法:
源碼文件裏,方法名稱 爲symbol(符號),相對概念是 內存地址,如LOG方法在 內存中的地址是什麼。
消除symbol
- 將method聲明爲inline。inline 方法的方法體,會被直接copy到 方法調用的地方。(也就是 鏈接階段是 沒有這個方法的)
inline void LOG(std::string s) { std::cout << s << std::endl; }
- 採用宏定義
#define LOG(s) (std::cout << s << std::endl)
,相當於不是方法了,就是文本替換了。
可見性
只在單個.o文件內可見
3. 將方法聲明爲static(表示方法不能被share,生成的symbol只在文件內可見)