为什么静态常量成员不能像'switch'一样出现在常量表达式中

14
我有一些静态常量成员的声明如下:
.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

在某个时候,我想要像这样在 switch 语句中使用这些值:

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

但我收到以下编译器错误:错误:'MyClass :: sInvalid'不能出现在常量表达式中

我阅读了其他关于 switch-cannot-appear-constant-stuff 的内容,但没有找到适合我的答案,因为我不知道为什么那些 static const unsigned char 不是常量表达式。

我正在使用gcc 4.5。

3个回答

19

你看到的问题是因为这个原因

static const unsigned char sInvalid;

由于编译器不知道它的值,因此无法作为编译时常量表达式。请在头文件中像这样初始化它们:

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

这样它就可以工作了。


错误地使用了 -1。你应该指定初始化应该在类定义内部,而不仅仅是头文件中。如果你在头文件中但类外初始化它们,你会得到链接错误。 - Luchian Grigore
4
对于一个有效的解决方案,我给一个赞,但我仍然认为枚举在这里更好。 - Luchian Grigore

9

这些值确实是const,但它们不是编译时常量

switch条件在编译时而非运行时之前解决。您可以将sInvalid初始化为任何值,只要它只有一次,switch直到运行时才会知道它的值。

看起来您最好使用enum代替static常量。除了工作原因外,从设计角度看似乎更合适。


感谢您宝贵的解释!枚举是我的首选,但我在其他地方使用这些常量进行位运算和大数组内容,我真的需要它们是“unsigned char”。我从未找到一种方法可以在不使用显式“unsigned char”类型的情况下使其正常工作。使用默认枚举并在每个地方将其转换为“unsigned char”会使代码难以阅读,所以我采用了这种解决方案。 - Thomas Vincent
你能解释一下常量和编译时常量的区别吗?(或者提供一个解释的链接?) - abcd

2
你可以使用枚举技巧将它们变成编译时常量:
class MyClass 
{
public:
    enum {
        sInvalid,
        sOutside,
        sInside,
        //(41 more ...)
    };
};

在你的代码中,你仍然可以使用枚举来分配给无符号字符,例如:

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)
}

并在你的switch语句中使用MyClass::sInvalid


是的,我真的需要它们是“unsigned char”,但我无法让“enum MyEnum:unsigned char”在我们使用的所有编译器版本中正常工作。 - Thomas Vincent
Switch不会介意。请看我的编辑,可以使用g++ 4.6.1 -Wall编译。 - ixe013

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接