2011-03-24 61 views
2

我正在使用Visual Studio 2008,並且有兩個類Parent和Child。 Parent在頭文件中聲明瞭一些靜態常量變量,然後在cpp文件中定義它們。當我嘗試在子類中的switch語句中使用定義作爲案例時,我得到以下錯誤:C2051:案例表達式不是常量。所以我做了一些測試,我看到的行爲有些不一致。靜態const變量在子類中不是常量

// Parent.h 
class Parent 
{ 
public: 
    Parent(); 
    ~Parent(void) { } 

    static const unsigned long A = 1; 
    static const unsigned long B; 
}; 


// Parent.cpp 
#include "Parent.h" 

const unsigned long Parent::B = 2; 

Parent::Parent() 
{ 
    // Everything works fine here 
    unsigned long l; 
    switch(l) 
    { 
    case A: 
    break; 
    case B: 
    break; 
    default: 
    break; 
    } 
} 

// Child.h 
#pragma once 
#include "Parent.h" 

class Child : 
    public Parent 
{ 
public: 
    Child(void); 
    virtual ~Child(void) { } 

    static const int C = 3; 
    static const int D; 
}; 

// Child.cpp 
#include "Child.h" 

const int Child::D = 4; 

Child::Child(void) 
{ 
    unsigned long l; 
    switch(l) 
    { 
    case A: 
    break; 
    case B: // C2051: case expression not constant 
    break; 
    case C: 
    break; 
    case D: 
    break; 
    default: 
    break; 
    } 
} 

我也試過直接指定Parent::B,這並沒有解決問題。除非變量是從父類繼承的,否則在所有情況下,爲什麼表達式都是不變的?

回答

7

如果

  • 它與一個常量表達式和初始化,則僅在一個常量表達式使用static const整數型構件變量
  • 該常量表達式是在它被使用的時間是可見的。

在你switch,因爲它的初始化是在Parent.h頭文件Parent::A值是可見的。 Child::C也是如此。 Child::D的值是可見的,因爲它的初始化器在Child.cpp中較早出現。

然而,Parent::B值是不可見的:C++源文件被單獨編譯,所以編譯Child.cpp時,編譯器知道Parent::Bstatic const整型成員變量,但它不知道它價值是。因此,它不能用於Child.cpp中的常量表達式中。


請注意,如果你曾經使用Parent::A作爲一個對象(例如,&Parent::A),你仍然需要定義Parent.cpp B,使用const unsigned long Parent::A;,沒有初始化,因爲你把初始化的類定義。

+0

請問,這是什麼原因?看起來很奇怪,因爲編譯時可以知道常量值。 – 2011-03-24 16:07:53

+0

@Antonio:我已經更新了我的回答,試圖解釋:基本上,這是因爲C++源文件是獨立編譯的。 – 2011-03-24 16:11:48

+0

@Antonio - 如果在編寫parent.cpp之前編譯child.cpp,則不知道。 – 2011-03-24 16:12:14

0

我很驚訝,Visual Studio讓你在類聲明之外聲明const。該行

static const unsigned long B; 

不應該被允許在您的父類。當我試圖在Mac上,它採用GNU G ++編譯器在你的榜樣,我得到了以下錯誤:

error: declaration of 'const long unsigned int Parent::B' outside of class is not definition 

至於爲什麼它適用於一類,而不是其他;我的猜測是:在child.cpp文件中,編譯器看到D確實被聲明爲const,但它不知道B是如何定義(或重新定義的)。要做到這一點,你應該將所有的常量聲明移到.h文件中的類中,而不是.cpp文件中。

0

原因是對於編譯器而言,static const不是常量,因此在編譯時它沒有一個值,編譯case語句時需要這個值。

稍後在鏈接時添加該值,當parent.o鏈接到child.o(請記住,使用插件或共享庫的鏈接時間可能會比運行時間晚)。