2012-05-16 49 views
12

我有一些靜態常量成員爲什麼靜態常量成員不能出現在常量表達式,如「開關」

.H

class MyClass : public MyBase 
{ 
public: 
    static const unsigned char sInvalid; 
    static const unsigned char sOutside; 
    static const unsigned char sInside; 
    //(41 more ...) 
} 

的.cpp

const unsigned char MyClass::sInvalid = 0; 
const unsigned char MyClass::sOutside = 1; 
const unsigned char MyClass::sInside = 2; 
//and so on 

以下宣言有一點我想在開關中使用這些值:

unsigned char value; 
... 
switch(value) { 
    case MyClass::sInvalid : /*Do some ;*/ break; 
    case MyClass::sOutside : /*Do some ;*/ break; 
    ... 
} 

但是我得到以下編譯器錯誤:錯誤:'MyClass :: sInvalid'不能出現在常量表達式中。

我已閱讀其他開關不能出現恆定的東西,並沒有找到我的答案,因爲我不明白爲什麼這些static const unsigned char不是恆定表達式。

我正在使用gcc 4.5。

回答

17

您所看到的問題的事實,這

static const unsigned char sInvalid; 

不能編譯時間常數表達式,因爲編譯器不知道它的價值是由於。在這樣的標題中初始化它們:

class MyClass : public MyBase 
{ 
public: 
    static const unsigned char sInvalid = 0; 
    ... 

它會工作。

+0

-1錯誤。您應該指定初始化應該在**類的定義內部,而不僅僅是頭部。如果您在標題中初始化它們,但在課程外部,則會出現鏈接錯誤。 –

+0

@LuchianGrigore:好的,我說得很清楚。 – jpalecek

+4

+1有效的解決方案,但我仍然是一個枚舉在這裏更好。 –

9

值確實const,但他們沒有編譯時常

A switch在編譯時解析條件,而不是運行時。您可以將sInvalid初始化爲任何值,只要它只有一次,並且switch直到運行時纔會知道它。

看起來你最好用enum而不是static常數。除了它會起作用的事實,它在設計上似乎更合適。

+0

感謝您的寶貴意見! Enum是我的第一選擇,但是我在別處使用那些常量,並且在大數組內容中,我真的需要它們是'unsigned char'。我從來沒有找到一種不使用明確的'unsigned char'類型就能正常工作的方法。使用默認的枚舉並將其轉換爲'unsigned char'處處使代碼如此無法收斂,以至於我無法使用此解決方案。 – vrince

+0

你能解釋一個常量和一個編譯時常量之間的區別嗎? (或鏈接到解釋?) – dbliss

2

可以使用枚舉技巧,使他們的編譯時間常數:

class MyClass 
{ 
public: 
    enum { 
     sInvalid, 
     sOutside, 
     sInside, 
     //(41 more ...) 
    }; 
}; 

在代碼中,你仍然可以使用枚舉assing爲unsigned char,這樣的事情:

int main(int argc, char *argv[]) 
{ 
    unsigned char buf[32]; 
    buf[0] = MyClass::sInvalid; //int to unsigned char 
    return buf[0]; //Cast back to int (and avoid a warning a -Wall) 
} 

並在swith語句中使用MyClass::sInvalid

+0

是的,我真的需要它們是'unsigned char',我無法使用'enum MyEnum:unsigned char'來處理所有我們正在使用的編譯器版本。 – vrince

+0

開關不會介意。看到我的編輯,用g ++ 4.6.1 -Wall編譯 – ixe013

相關問題