2011-04-09 17 views
0
A.h 

class A 
{ 
    private: 
    static const int b = 50; 
    int c[b]; 
}; 

A.cpp 

#include "A.h" 
const int A::b; 

C.cpp 

#include "A.h" 

編譯器向我發出一條警告,說b被定義了多次,而一個被忽略。我需要在類中定義它,因爲我需要初始化數組。或者我需要使用枚舉方法來做到這一點。但我想知道這是否可能?在.h文件包含在多個cpp文件中的類中定義了整型靜態常量

+0

你正在使用哪種編譯器?我在Ubuntu上用g ++試了這個(添加了一個存根'main()',這樣鏈接器就可以運行)並且根本沒有任何警告。 「 – QuantumMechanic 2011-04-09 02:16:39

回答

6

我要猜你正在使用Visual C++,它有一個相當可怕的語言擴展,如"Microsoft Extensions to C and C++"描述:

出靜態常量積分(或枚舉)成員的類定義的

根據標準(/Za),您需要爲數據成員創建一個類外定義。例如,

class CMyClass { 
    static const int max = 5; 
    int m_array[max]; 
} 
... 
const int CMyClass::max; // out of class definition 

/Ze,外的類定義是可選的靜態,常量積分,和const枚舉數據成員。只有static和const的整數和枚舉可以在類中有初始化方法;初始化表達式必須是一個const表達式。

爲避免出現類外定義時的錯誤(當頭文件中提供了超類定義並且頭文件包含在多個源文件中時),應該使用selectany。例如:

__declspec(selectany) const int CMyClass::max = 5; 

/Ze標誌默認情況下啓用。如果您不想使用語言擴展名,則必須明確使用/Za標誌。

使用g ++ 4.5.2,Clang 3.0和Visual C++ 2010以及/Za標誌設置,所編寫的代碼按原樣編譯和鏈接,沒有錯誤。

從.cpp文件中刪除定義解決了如果要使用Visual C++進行編譯的問題,但是如果嘗試使用數據成員,則不能與其他編譯器一起使用(或與/Za一起使用)。對於便攜式解決方法,可以使用條件編譯模塊檢查擴展是否已啓用:

#ifndef _MSC_EXTENSIONS 
const int A::b; 
#endif 
+1

」但是那麼你的代碼將不能與其他編譯器一起工作「這是不正確的。該代碼將編譯並運行良好的gcc,(只是verfied)。也許你可以提供一個編譯器的例子,其中該行真的是必要的? – 2011-04-09 02:38:35

+0

@Matt:在這個特定的案例中,定義是不必要的,因爲靜態數據成員不是_used_(在術語的一個定義規則的意義上)。如果靜態數據成員被_used_(例如,如果'&A :: b'出現在程序的某處),你肯定會得到一個鏈接錯誤。如果您不打算使用數據成員,則首選方法是使用枚舉來阻止_use_,例如, 'enum {b = 50};'。 – 2011-04-09 02:46:25

+0

@Matt:你說的沒錯,我說「你的代碼不行」。我的意思並不是說「你在這裏發佈的特定代碼將不起作用,」我的意思是「一般來說,你編寫的代碼將不起作用。」我澄清了那句話。感謝您指出了這一點。 – 2011-04-09 02:50:32

0

您已經給出了衝突的定義。通過在類定義中給這個變量賦一個值,你說這是一個編譯時常量,不需要任何存儲。然後你試圖將它存儲在.cpp文件中。

把它從.cpp中拿出來,你會沒事的。只是不要試圖說明它的地址。

+0

並且不要嘗試綁定對它的引用,或[使用它在某些形式的條件表達式中](http://stackoverflow.com/questions/5446005)。如果只使用枚舉,使用非定義的整型靜態數據成員是否有任何好處? – 2011-04-09 03:02:37

相關問題