1. 程式人生 > >錯誤:“LNK1169找到一個或者多個重定義的符號”

錯誤:“LNK1169找到一個或者多個重定義的符號”

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">今天自己寫了一個頭檔案,然後依照書上推薦的“宣告和實現分離”方法,把類的成員函式寫在標頭檔案和head1.h裡,然後把實現寫在c1.cpp檔案裡。</span>
class CXX{
public:
static int k;
};

在類中,我聲明瞭一個靜態變數。開始怎麼也無法使用,發生錯誤:LNK2001 無法解析的外部符號……

後來查資料才知道,是使用靜態變數方法不對,使用靜態變數必須在外部定義它才行。

class CXX{
...
};
int CXX::k;
後來,程式碼越來越多,我就又寫了另一個頭檔案head2.h,又寫了一個c2.cpp檔案,在這個cpp檔案裡,用到了head.1的類。

然後,編譯的時候就出錯了。

“LNK1169找到一個或者多個重定義的符號”
重定義?我仔細檢查了,並沒有發現重名的情況。我注意到編譯資訊裡說的,好像正是我之前定義的那個靜態變數!

我理解的是,因為重複引用標頭檔案,導致定義了兩次變數。

於是我試著在標頭檔案前加上預編譯指令:

#ifndef HEAD1
#define HEAD1
...
#endif

這樣來似乎能防止重複定義?但是!!依然出錯!!

為什麼巨集定義沒有起作用?

為什麼編譯第二次的時候無視了預處理指令?

。。。

等等,無視?

我突然明白了,預處理指令只對當前檔案起作用!在連結前,每個obj檔案的生成都是互不相干的!

那這麼一來,問題解決了。只需要把放在標頭檔案裡的變數定義移動到cpp檔案即可。

原因是在引用標頭檔案時,編譯器是將標頭檔案的全部放到cpp前,在兩個cpp檔案生成obj後,自然會有兩次定義,但是放到cpp檔案中,就沒有問題了。

一般來說,標頭檔案裡最好只放宣告,不放定義,除非某些特殊原因一定要放在標頭檔案裡(在另外一篇文裡就會提到這種情況)。這好像又繞回了文章開頭,宣告就像一個多孔介面,大家都能用,但是介面的實現是隻有一個的,如果有很多實現,就不知道該呼叫那個實現了。