【问题标题】:Why static const members cannot appear in a constant expression like 'switch'为什么静态常量成员不能出现在像'switch'这样的常量表达式中
【发布时间】:2012-05-16 13:01:02
【问题描述】:

我有一些静态常量成员的以下声明

.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' 不能出现在常量表达式中

我已阅读其他 switch-cannot-appear-constant-stuff 并没有为我找到答案,因为我不明白为什么那些 static const unsigned char 不是常量表达式。

我使用的是 gcc 4.5。

【问题讨论】:

    标签: c++ gcc constants switch-statement


    【解决方案1】:

    你看到的问题是因为这个

    static const unsigned char sInvalid;
    

    不能是编译时常量表达式,因为编译器不知道它的值。像这样在标题中初始化它们:

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

    它会起作用的。

    【讨论】:

    • -1 错误。您应该指定初始化应该在类定义内部,而不仅仅是标题。如果你在标题中初始化它们,但在类之外,你会得到链接错误。
    • +1 是一个有效的解决方案,但我仍然认为枚举在这里更好。
    【解决方案2】:

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

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

    看起来你最好使用enums 而不是static 常量。除了它可以工作之外,它似乎更适合设计。

    【讨论】:

    • 感谢您的宝贵解释! Enum 是我的第一选择,但我在其他地方使用这些常量进行逐位操作和大数组内容,我真的需要它们是 unsigned char。如果不使用明确的unsigned char 类型,我从来没有找到让它正常工作的方法。使用默认 Enum 并将其转换为 unsigned char 无处不在使代码难以阅读,以至于我使用此解决方案。
    • 你能解释一下常量和编译时常量之间的区别吗? (或解释的链接?)
    【解决方案3】:

    您可以使用枚举技巧使它们成为编译时常量:

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

    在你的 swith 语句中使用MyClass::sInvalid

    【讨论】:

    • 是的,我真的需要他们成为 unsigned char,但我无法让 enum MyEnum : unsigned char 与我们正在使用的所有编译器版本一起工作。
    • Switch 不会介意。查看我的编辑,使用 g++ 4.6.1 -Wall 编译
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2019-11-13
    • 2011-11-15
    • 1970-01-01
    相关资源
    最近更新 更多