2

我正在使用 Visual Studio 2008 并且有两个类 Parent 和 Child。Parent 在 header 中声明了一些静态 const 变量,然后在 cpp 文件中定义这些变量。当我尝试在子类的 switch 语句中将定义用作 case 时,出现错误:C2051: case expression not constant。所以我做了一些测试,我看到的行为有些不一致。

// 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直接指定,但这并不能解决问题。除了从父类继承变量时,表达式在所有情况下都是常量是否有某种原因?

4

3 回答 3

7

您只能static const在常量表达式中使用整数类型的成员变量,如果

  • 它用一个常量表达式初始化,并且
  • 该常量表达式在使用时可见。

在您的switch中, 的值Parent::A是可见的,因为它的初始化程序位于 Parent.h 头文件中。也是如此Child::C。的值Child::D是可见的,因为它的初始值设定项在 Child.cpp 中较早出现。

但是,值Parent::B是不可见的:C++源文件是单独编译的,所以在编译Child.cpp时,编译器知道Parent::Bstatic const整数类型的成员变量,但不知道它的值是什么。因此,它不能用于 Child.cpp 中的常量表达式。


请注意,如果您曾经将Parent::A其用作对象(例如,&Parent::A),您仍然需要B在 Parent.cpp 中使用进行定义const unsigned long Parent::A;,而无需使用初始化程序,因为您将初始化程序放在类定义中。

于 2011-03-24T15:58:05.337 回答
0

我很惊讶 Visual Studio 允许您在类声明之外声明 const。线

static const unsigned long B;

不应允许在您的 Parent 类中。当我在使用 GNU g++ 编译器的 Mac 上尝试您的示例时,出现以下错误:

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

至于为什么它适用于一个类,而不适用于另一个类;我的猜测:在 child.cpp 文件中,编译器看到 D 确实被声明为 const,但它不知道 B 是如何定义(或重新定义)的。为了使这项工作,您应该将所有常量声明移动到 .h 文件中的类而不是 .cpp 文件中。

于 2011-03-24T16:12:47.867 回答
0

原因是编译器static const不是常量,因为在编译时它还没有编译case语句所需的值。

该值稍后在链接时添加,当parent.o链接到时child.o(请记住,对于插件或共享库,链接时间可能与运行时一样晚)。

于 2011-03-24T16:14:22.887 回答