2012-05-16 9 views
12

tengo la siguiente declaración de algunos miembros static constmiembros const estáticos Por qué no pueden aparecer en una expresión constante como 'interruptor'

.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 

En algún punto quiero usar esos valores en un interruptor como:

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

Pero aparece el siguiente error de compilación: error: 'MyClass :: sInvalid' no puede aparecer en una expresión constante.

He leído otras palabras de cambio-no-aparece-constante-cosas y no he encontrado una respuesta para mí ya que no entiendo por qué esos static const unsigned char no son expresión constante.

Estoy usando gcc 4.5.

Respuesta

17

Los problemas que se ven son debido al hecho de que este

static const unsigned char sInvalid; 

no puede ser una expresión constante de tiempo de compilación, ya que el compilador no conoce su valor. Inicialícelos en el encabezado como este:

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

y funcionará.

+0

-1'd por error. Debe especificar que la inicialización debe ser ** dentro ** de la definición de clase, no solo el encabezado.Si los inicializa en el encabezado, pero fuera de la clase, obtendrá errores de enlace. –

+0

@LuchianGrigore: OK, lo dejé claro. – jpalecek

+4

+1 para una solución válida, pero aún creo que una enumeración es mejor aquí. –

9

Los valores son de hecho const, pero no son constantes de tiempo de compilación.

Una condición switch se resuelve en tiempo de compilación, no en tiempo de ejecución. Puede inicializar sInvalid a cualquier valor, siempre que sea solo una vez, y switch nunca lo sabrá hasta el tiempo de ejecución.

Parece que es mejor utilizar enum s en lugar de static constantes. Además del hecho de que funcionaría, parece más apropiado para el diseño.

+0

Gracias por su valiosa explicación! Enum fue mi primera opción, pero estoy usando esas constantes en otros lugares en operaciones de mordida y en gran cantidad de contenido, realmente necesito que sean 'char sin signo'. Nunca encontré la manera de hacerlo funcionar correctamente sin usar tipos explícitos de "caracteres sin signo". Usar Enum por defecto y convertirlo en 'char sin signo' en todas partes hace que el código sea tan imposible de leer que cam con esta solución. – vrince

+0

¿Puedes explicar la diferencia entre una constante y una constante de tiempo de compilación? (o el enlace a una explicación?) – dbliss

2

Puede utilizar el truco de enumeración de hacer constantes de ellos en tiempo de compilación:

class MyClass 
{ 
public: 
    enum { 
     sInvalid, 
     sOutside, 
     sInside, 
     //(41 more ...) 
    }; 
}; 

En su código, puede seguir utilizando la enumeración de assing a unsigned char, algo como esto:

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

Y use MyClass::sInvalid en sus declaraciones swith.

+0

Sí, realmente necesito que sean 'unsigned char' y no pude hacer que' enum MyEnum: unsigned char' funcione con toda la versión del compilador que estamos usando. – vrince

+0

Cambiar no le importará. Ver mi edición, compila con g ++ 4.6.1 -Wall – ixe013

Cuestiones relacionadas