關於函式實現在標頭檔案(.h)中造成的一個問題
阿新 • • 發佈:2019-01-02
問題描述:
在專案中遇到一個問題,把一個比較簡短但是經常(包括其他檔案中的使用)使用的函式放在標頭檔案中實現,造成了一個連結錯誤。
<span style="font-family: Arial, Helvetica, sans-serif;">// file1. h 預處理巨集 #ifndef __FILE1_H__ 等省了沒寫,下同。</span>
void function( )
{
;
}
// file2.h
#include "file1.h"
void f ( );
// file2.cpp
void f( )
{
function();
}
// file3.cpp #include "file1.h" #include "file2.h" function( ); f( );
編譯通過,連結出錯。分析原因,在編譯c++檔案時候,編譯器把每一個cpp檔案作為一個獨立的編譯單元,在每次編譯一個檔案的時候編譯器都重新執行是一個獨立的程序,比如在linux系統中經常適用的命令 gcc file3.cpp ,得到 一個obj檔案,最後經過連結得到可執行檔案。在編譯之前,所包含的標頭檔案被包含到cpp中,所以在編譯file2.cpp得到的file2.obj中存在一個關於function函式的符號;同樣的在編譯file3.cpp的時候包含了file1.h,在編譯file3.cpp得到的file3.obj中也有一個function函式的符號,在連結的時候出現相同的符號將導致重複定義而連結錯誤。
解決辦法:
1,把file1.h 中的函式 function 的實現放到file1.cpp中去,這樣在編譯時候function函式的符號只在file1.cpp中出現一次,連結可以通過。
2,在file3.cpp中對於function函式使用外部引用:
extern void function( ); // 這樣在編譯file3.cpp時,編譯器把function函式當作外部引用方法,不會為它建立對應的符號,連結時也可以通過。
3,建議函式的實現都放到cpp中去,一來對於函式的實現可以得到較好的隱藏,而來也方便該模組的擴充套件,有時候我比較喜歡偷懶總覺得少一個類少一個檔案更好,其實不然吧,專案儘量的模組化,物件化,不要怕麻煩而少寫一些東西。