2014-02-10 25 views
0

我只是建立一個簡單的C++項目。的代碼被顯示在如下:多個包含具有可變定義的頭文件

-------- -------- head.h

#ifndef _HEAD_H_ 
#define _HEAD_H_ 

int my_var = 100; 

#endif 

-------- src1.cpp - -------

#include "head.h" 

-------- -------- src2.cpp

#include "head.h" 
int main() { return 0; } 

我建立二進制與命令:

g++ -c src1.cpp -o scr1.o 
g++ -c src2.cpp -o src2.o 
g++ -o a.out src2.o src1.o 

但它在連接步驟失敗,並告訴我,我有「my_var'的多重定義。我不是在頭文件中使用安全防護宏嗎?我不明白。有人知道爲什麼

謝謝。

ps: 如果我將my_var定義爲一個靜態變量,那麼代碼可以傳遞鏈接。我也不明白。

+0

在所有情況下,嘗試對源文件進行心理預處理,就好像您是GCC的預處理器一樣。也許它會帶來一些清晰。另外,值得一提的是,在C++中,你必須避免任何全局變量。 – Drop

回答

3

更改報頭中的以下方式

#ifndef _HEAD_H_ 
#define _HEAD_H_ 

extern int my_var; 

#endif 

而且例如在模塊中添加符合主

#include "head.h" 
int my_var = 100; 
int main() { return 0; } 

的問題是,作爲標題被包括在兩個模塊然後每個模塊包含與其他模塊中的變量具有相同名稱的外部鏈接的變量。鏈接器不知道使用哪個變量。

2

您正在爲每個彙編單元定義my_var一次。請記住,包括警衛在每個編譯單元的基礎上運行。

爲了彌補,在標題,你應該聲明my_varextern:使用

int my_var = 100; 

,則鏈接只看到

#ifndef _HEAD_H_ 
#define _HEAD_H_ 

extern int my_var; 

#endif 

在源文件中的一個定義它一個定義,一切都會好的。

1

防護只防止在同一個編譯單元中包含兩次標題。

當您編譯src1.osrc2.o時,每個將包含一個定義my_var。鏈接它們以創建a.out時,編譯器無法合併這些定義(即使它們是相同的)並且失敗。

你想要做什麼是聲明my_varextern

----頭。^ h ----

#ifndef _HEAD_H_ 
#define _HEAD_H_ 

extern int my_var; 

#endif 

---- ---- my_var.c

#include "head.h" 

int my_var = 100; 

然後編譯所有源文件:

g++ -c my_var.cpp -o my_var.o 
g++ -c src1.cpp -o scr1.o 
g++ -c src2.cpp -o src2.o 
g++ -o a.out my_var.o src2.o src1.o 

這樣,my_var在每個文件中都聲明爲,但只會在中定義爲my_var.o。這裏有一個重要的區別。嘗試省略鏈接my_var.o,你會看到編譯器說的:)

0

你的問題歸結爲理解C++存儲類;更精確的靜態和外部。

extern says: this variable is defined in a different file, this 
      is only a declaration 
static says: this variable's lifetime is the program lifetime and 
      restrict it's visibility to the current file. 



What happens in your case: 
    - each file includes the variable declaration and definition `int my_var = 100;`, 
    so both object scr1.o and scr2.o will contain the variable definition. When 
    linking them, the linker cannot solve the ambiguity and throws an error. 
    - adding the extern qualifier and defining the variable in one of the files 
    solves this problem: in one source it'll be an external unresolved at compile 
    time, symbol and the other will contain the actual symbol. 

至於你的問題的第二部分;爲什麼添加靜態似乎有助於鏈接器。看看我剛剛提到的靜態存儲類:基本上每個對象都有自己的變量副本 - 不是同一個!

+0

爲什麼用C++語言設計靜態變量?如果頭文件中定義的一個靜態變量在多個cpp文件中使用,但實際上每個cpp文件都包含它自己的變量副本,那麼這是項目中的一個巨大陷阱嗎? – coinsyx

+0

ps:所有書籍都說靜態變量只在當前文件中可見。文件只是頭文件還是cpp文件包含頭文件?我認爲靜態變量對包含它的cpp文件是可見的。 – coinsyx

+0

發生了什麼,由於您在頭文件中定義變量的方式,每個源文件都將變量定義包含爲靜態;所以它們的可見性僅限於當前文件。從編譯器的角度來看,這些是兩個獨立的變量 – Pandrei

相關問題