Вопрос по c++, const, switch-statement, gcc – Почему статические члены const не могут появляться в постоянном выражении, таком как «switch»

13

У меня есть следующее объявление некоторых статических членов const

.час

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;
    ...
}

Но я получаю следующую ошибку компилятора:error: 'MyClass::sInvalid' cannot appear in a constant-expression.

Я прочитал другое переключение-не могу-появиться-постоянный материал и не нашел ответа для меня, так как я не понимаю, почему теstatic const unsigned char не являются константным выражением.

Я использую GCC 4.5.

Ваш Ответ

3   ответа
9

Значения действительноconstно они неcompile-time constants.

switch условие разрешается во время компиляции, а не во время выполнения. Вы можете инициализироватьsInvalid к какому-либо значению, если только один раз, иswitch никогда не узнает об этом до времени выполнения.

Похоже, вы лучше используетеenumс вместоstatic константы. Помимо того, что он будет работать, он кажется более подходящим по дизайну.

Можете ли вы объяснить разницу между константой и константой времени компиляции? (или ссылка на объяснение?)
Спасибо за ваше ценное объяснение! Enum был моим первым выбором, но я использую эти константы в других местах при работе с кусочками и в большом массиве контента, мне действительно нужно, чтобы они былиunsigned char, Я никогда не находил способ заставить это работать должным образом без использования явногоunsigned char типы. Использование Enum по умолчанию и приведение его кunsigned char везде делают код настолько нечитаемым, что я использую это решение. vrince
2

Вы можете использовать трюк enum, чтобы сделать их константами времени компиляции:

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

И использоватьMyClass::sInvalid в ваших утверждениях.

Переключатель не возражает. Смотрите мои правки, компилируется с g ++ 4.6.1 -Wall
Да, мне действительно нужно, чтобы они былиunsigned char и я не смог сделатьenum MyEnum : unsigned char работать со всеми версиями компилятора, которые мы используем. vrince
18

Проблемы, которые вы видите, связаны с тем, что это

static const unsigned char sInvalid;

не может быть выражением константы времени компиляции, так как компилятор не знает его значения. Инициализируйте их в заголовке так:

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

и это будет работать.

+1 для правильного решения, но я все еще считаю, что перечисление здесь лучше.
@LuchianGrigore: хорошо, я ясно дал понять.
-1 'd по ошибке. Вы должны указать, что инициализация должна бытьinside определение класса, а не только заголовок. Если вы инициализируете их в заголовке, но вне класса, вы получите ошибки ссылок.

Похожие вопросы