曾經多次在寫程式時遇到這個問題,每次遇到這個問題就積累一下
首先這類問題的原因在於鏈結的時候出錯,vs在編譯的過程中,專案中所有的cpp都會生成乙個對應的obj檔案,也就是乙個cpp檔案會生成乙個.obj的可重定位目標檔案,和linux中用命令g++ -c .cpp一樣,得到cpp檔案的單獨的二進位制檔案,接下來就是把多個obj檔案鏈結成乙個可執行檔案。不管vs還是linux的g++編譯器,都是乙個cpp檔案生成乙個obj或者o檔案。
錯誤都是現實***.obj檔案中已經定義,所以不是語法的問題,是多個obj檔案中有相同的內容。
1.error lnk2005: "int a" (?a@@3ha) 已經在 a.obj 中定義
詳細解釋看鏈結
也就是在乙個大程式中,乙個標頭檔案如果既被其他標頭檔案或者主程式引用不止一次,那麼在該標頭檔案中不能定義全域性變數和全域性函式。
2.error lnk2005: "int __cdecl test3(void)" (?test3@@yahxz) 已經在 main.obj 中定義
使用的是vs2013編譯器,該專案結構如下
其中main.cpp程式如下
#include #include "test.cpp"
using namespace std;
int main(void)
test.cpp程式如下
#include extern int a;
static int b = 100;
int test3()
這裡的錯誤有兩點:
1.沒有函式原型宣告,這個宣告應該加到cpp檔案的函式定義前面。(但是加了以後還是不對,這是錯誤2造成的)
2.這個錯誤才是整個錯誤的核心,在這個函式中使用了很少見得include cpp檔案,這樣原理上是可以的,但是問題出在鏈結步驟上了。
首先要明確的前提:
vs在編譯的過程中,乙個cpp檔案會生成乙個.obj的可重定位目標檔案,和linux中用命令g++ -c .cpp一樣,得到cpp檔案的單獨的二進位制檔案,接下來就是把多個obj檔案鏈結成乙個可執行檔案。不管vs還是linux的g++編譯器,都是乙個cpp檔案生成乙個obj或者o檔案。
以上的例子中就生成了兩個obj檔案main.obj和test.obj檔案。但是由於main.cpp檔案中include了test.cpp檔案,在預處理時,#include "test.cpp"就會被test.cpp檔案中的具體內容給替換,所以main.obj和test.obj兩個二進位制檔案中都有test.cpp中的內容,因此在鏈結時,是將這兩個obj合併成乙個obj,這樣就會產生函式或者變數的重定義,比如這個程式中就兩次定義了test3函式。
解決辦法:第一種include標頭檔案,這樣在main.cpp檔案預處理時,複製的內容就是標頭檔案的內容,就不會產生變數或者函式的重定義。因為標頭檔案是不會生成obj檔案的。
第二種辦法,在test3函式前加inline,變為內建函式,具體原理不明,但是嘗試可以使用
第三種辦法,將test.cpp從工程中去除
也就是在這裡刪除test.cpp,但不要刪除原始檔,繼續include,這樣只會產生乙個main.obj檔案。
注意:所以在程式設計時,標頭檔案中引用標頭檔案,定義全域性變數,一定要慎重考慮,而原始檔中就沒有這麼多顧慮了。
VC重定義問題
錯誤 1 e program files windows mobile 6 sdk pocketpc include armv4i winsock2.h 554 warning c4005 af max 巨集重定義 1 e program files windows mobile 6 sdk poc...
新增windows h出現重定義的問題
有時候新增標頭檔案windows.h之後會出現 warning c4005 af ipx 巨集重定義 warning c4005 af max 巨集重定義 error c2011 sockaddr struct 型別重定義 之類的錯誤 原因就是windows.h和winsock2.h之間包含順序問題...
swig包裝lua重定義問題
在用swig封裝lua時,會遇到函式 set函式或者 get函式重定義的錯誤,究其原因,是因為swig為每個結構體新增乙個get或者set函式,用來訪問結構體成員。如struct a int a swig會生成乙個名為 wrap a a get的函式來訪問變數 a 如果你剛好自己定義了乙個函式a a...