2011-03-24 59 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(请记住,使用插件或共享库的链接时间可能会比运行时间晚)。