2012-07-24 122 views
26

我有一個命名空間foo其中包含一個整數bar,宣佈所以...靜態VS在命名空間的非靜態變量

了foo.h:

namespace foo { 
    int bar; 
} 

現在,如果我有foo.h只有一個文件,這工作得很好。但是當我從兩個或多個文件中包含foo.h時出現問題:出現連接器錯誤。我發現如果我宣佈barstatic,我可以在一個以上的文件中包含foo.h。這對我來說似乎很陌生,因爲我不知道可以在名稱空間內聲明一個靜態變量。 (這是什麼意思?)

這是爲什麼?更重要的是,爲什麼不是它的工作沒有static?當在namespace中使用時,static是什麼意思?

+0

Upvote。是我的問題,並解決它:) – 2014-07-01 17:12:18

回答

26

static在不同的環境中有多種含義。在這個特定的上下文中,這意味着變量具有內部鏈接,因此包含該頭文件的每個翻譯單元都將擁有自己的變量副本。

請注意,儘管這樣可以避免鏈接器錯誤,但它將爲每個生成的對象文件(在不同的對象文件間都無法看到更改)保留單獨的foo::bar變量。

如果你想要一個變量,你應該在頭文件中聲明它爲extern,並在一個翻譯單元中提供一個單一的定義。

19

當您聲明一個變量爲static時,這意味着它的範圍僅限於給定的翻譯單元。沒有static範圍是全球性的。

當一個變量聲明爲static .h文件(在或不在namespace;無所謂)內,並且包括在不同的cpp文件該頭文件中,變量static變得局部範圍到每個.cpp的文件。
所以現在,包含該頭文件的每個.cpp文件都將擁有自己的該變量副本。

如果沒有static關鍵字,編譯器將只生成該變量的一個副本,因此只要將頭文件包含在多個.cpp文件中,鏈接器就會抱怨多個定義。

3

該問題是由變量的多個定義引起的。不同翻譯單元中的定義相互衝突,就像多個非內聯函數定義不起作用。

當您將變量設置爲靜態時,您會給出可變的內部鏈接,因此每個翻譯單元都有自己的獨立副本。

你可能真正想要的只是將聲明放在一個頭文件中(使用extern),然後將該定義放在一個實現文件中。