2015-12-10 101 views
4

我有一個宏,我用它來向註冊表映射添加鍵值。 (假設AddToMap位於全局靜態對象上,並在其他地方定義了一些其他對象。) 在定義了不同的類(某種類的註冊表)之後,在代碼中的各個位置調用AddKey宏。代碼分爲許多具有複雜依賴性的.h和.cc文件。C++類的靜態函數成員中的靜態數據成員初始化順序

我有下面這段代碼的工作原理:

#define AddKey(key, val)\ 
namespace NSP_##key {\ 
class A {\ 
    public:\ 
     static bool foo() {\ 
     static bool dummy = AddToMap(#key, #val);\ 
}\ 
};\ 
static bool dummy_A = A::foo();\ 
} 

`

我想知道的是如何創建和初始化靜態變量假人。當我使用GDB時,我發現這個A :: add在main或main之前被調用,如果被調用。這是對靜態變量的期望。

但是,如果我從類更改爲函數,則代碼似乎沒有工作了,並抱怨說,「密鑰已經被添加」

#define AddKey(key, val)\ 
namespace NS_##key {\ 
    static bool A_foo() {\ 
    static bool dummy = AddToMap(#key, #val);\ 
}\ 
static bool dummy_A = A_foo();\ 
} 

我明白dummy_A必須是靜態的,因爲一C++中的定義規則和A_foo()的相同原因。但爲什麼靜態函數中的靜態變量虛擬行爲與靜態類中的靜態成員時不同?

+1

你在頭文件擴展'AddKey'? – aschepler

+0

是的。有一個在cc文件中擴展的GetValue,AddKey在頭文件中展開。 –

回答

1

在一個類中,關鍵字static不影響鏈接,但表示它獨立於類對象。無論您有多少次AddKey(MyClass, hello),只有一個功能NSP_MyClass::A::foo(),它只需要調用AddToMap一次。

在類或函數之外,static關鍵字給出了名稱的內部鏈接,意味着每個包含它的編譯單元都有其自己的該名稱版本。因此,在第二個示例中,每個包含AddKey(MyClass, hello)的* .cc文件都有一個不同的函數NS_MyClass::A_foo()。這些功能中的每一個都會嘗試撥打AddToMap一次,給您帶來碰撞問題。

使用inline而不是static有在頭文件中的函數定義,但有它確實是相同的功能,每次:

#define AddKey(key, val)\ 
namespace NS_##key {\ 
    inline bool A_foo() {\ 
     static bool dummy = AddToMap(#key, #val);\ 
    }\ 
    static bool dummy_A = A_foo();\ 
} 
+0

這似乎工作順利。內聯似乎確保它是跨板的單實例,畢竟.cc文件是鏈接的。謝謝 –