重定義問題的解釋

2021-09-11 18:11:18 字數 1778 閱讀 5664

曾經多次在寫程式時遇到這個問題,每次遇到這個問題就積累一下

首先這類問題的原因在於鏈結的時候出錯,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...