2012-01-19 9 views
10

Aquí está mi código:¿Por qué no puedo tener una variable en la declaración de mayúsculas y minúsculas?

bool Character::keyPress(char c) 
{ 
    switch(c) 
    { 
     case up_key: 
      move(0, -1); 
      break; 

     case down_key: 
      move(0, 1); 
      break; 

     case left_key: 
      move(-1, 0); 
      break; 

     case right_key: 
      move(1,0); 
      break; 

     default: 
      return false; 
    } 

    return true; 
} 

y el compilador se queja:

error C2051: case expression not constant 
error C2051: case expression not constant 
error C2051: case expression not constant 
error C2051: case expression not constant 

En mi archivo de cabecera que tengo:

protected: 
    char up_key; 
    char down_key; 
    char right_key; 
    char left_key; 

estoy usando Visual C++ 2008.

+2

Las expresiones de mayúsculas y minúsculas deben ser constantes de tiempo de compilación. cámbielos a 'static const char up_key = 1;' y demás, y resuelva el problema. –

+1

Porque el estándar lo dice.Es un remanente de los viejos tiempos, donde "switch" se introdujo como una presentación "más agradable" que se transformó en una búsqueda de matriz automágicamente (y por lo tanto requiere constantes). Hoy en día tiene menos sentido, pero la sintaxis no se ha modificado, así que ... –

Respuesta

14

Como indica el mensaje de error, las expresiones de caso deben ser constantes. El compilador crea esto como una tabla de consulta muy rápida en tiempo de compilación y no puede hacerlo si existe la posibilidad de que los valores cambien a medida que se ejecuta el programa.

Si necesita que sean variables, no constantes, su mejor opción es usar sentencias if/else en su lugar.

+0

¿es posible de alguna manera "ver" el resultado del compilador en este caso, y quizás compararlo con if/else? –

1

No se puede porque el lenguaje no funciona de esa manera. Por ejemplo, ¿qué pasaría si up_key, down_key, right_key y left_key fueran iguales?

+0

, veo lo que quieres decir. Pero si uso if/else y todos son iguales? – infinitloop

+0

En realidad, puede tener el mismo valor aquí más de una vez, aunque siempre terminará en el primero de la lista. Con if/else, también, llegarás al primero y nunca a los posteriores. – Janne

+3

Incluso si fueran todas constantes, que es el aspecto crucial aquí, los valores en los casos deben ser todos distintos. Pero la distinción no es el problema, es la falta de constness. –

1

Como la instrucción switch solo puede tomar constantes, al leer el código, usted sabe que las cosas con las que compara son todas constantes. Por otro lado, se usaría if declaraciones (o alguna otra estructura) con el que comparar las variables:

if (c == up_key) { 
    move(0, -1); 
} else if (c == down_key) { 
    move(0, 1); 
} else ... 

Esto proporciona una clara diferencia en estructura que puede ser de gran ayuda a los que vienen después de la lectura de su código. Imagínese si tuviera que buscar cada etiqueta case para ver si era una variable o no.

+0

yup, eso es lo que voy a hacer, gracias. – infinitloop

1

Creo que es porque el compilador genera una tabla de salto, con los valores codificados, aunque puedo estar equivocado. La forma en que se generan las tablas simplemente no lo permite.

1

Dado que otras respuestas han cubierto por qué está obteniendo un error, aquí hay una manera de moverse en una de las cuatro direcciones en respuesta a una pulsación de tecla: use tablas de búsqueda en lugar de los condicionales/interruptores.

parte de configuración:

std::map<char,pair<int,int> > moves; 
moves[up_key] = make_pair(0, -1); 
moves[down_key] = make_pair(0, 1); 
moves[left_key] = make_pair(-1, 0); 
moves[right_key] = make_pair(1, 0); 

La función:

bool Character::keyPress(char c) { 
    if (moves.count(c)) { 
     pair<int,int> dir = moves[c]; 
     move(dir.first, dir.second); 
     return true; 
    } else { 
     return false; 
    } 
} 
0
//here is the full functional code snippet which can be compiled and run with most of C++ 
//compiler/link ...console app was demoed but you can apply the code/logic to win32 app... 
//if you have any problem, send me email to [email protected] 

#include <iostream.h> 
#include <map> 
#include <conio.h> 

class CkbdHanler{ 
    private: 
    map<char,pair<int,int> > moves; 
    protected: 
    char up_key; 
    char down_key; 
    char right_key; 
    char left_key; 
    public: 

CkbdHanler(char a,char b,char c,char d):up_key(a), 
             down_key(b), 
             right_key(c), 
             left_key(d) 
{ 
    moves[up_key] = make_pair(0, -1); 
    moves[down_key] = make_pair(0, 1); 
    moves[left_key] = make_pair(-1, 0); 
    moves[right_key] = make_pair(1, 0); 
} 

bool keyPress(char c){ 
    if (moves.count(c)) { 
      pair<int,int> dir = moves[c]; 
      move(dir.first, dir.second); 
      return true; 
    } else return false; 

} 
void move(int i,int j){ 
    cout<<"(i,j)=("<<i<<","<<j<<")"<<endl; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    CkbdHanler CmyKbdH('u','d','l','r'); 

    cout << "Hello C++... here is a demo of Map to replace switch-case" << endl; 
    CmyKbdH.keyPress('d'); 
    cout << endl << "Press any key to continue..."; 

    getch(); 
    return 0; 
} 
7

sustituir este código largo torpe,

switch(c) 
{ 
    case up_key: 
     move(0, -1); 
     break; 

    case down_key: 
     move(0, 1); 
     break; 

    case left_key: 
     move(-1, 0); 
     break; 

    case right_key: 
     move(1,0); 
     break; 

    default: 
     return false; 
} 

con algo como esto:

move((c==right_key) - (c==left_key) , (c==down_key) - (c==up_key)); 

Puede reemplazar el código de 17 líneas de largo con esa única línea de código única.

+8

¿Qué te hace pensar que ese código es limpio? – EralpB

+1

It * is * a neat line - tal vez debería agregar un pequeño comentario explicativo al código para ayudar a los tipos de lectura difícil;) – slashmais

+2

¿no aumenta la complejidad del tiempo? ¡4 comparaciones, 4 conversiones de tipo y 2 operaciones artísticas se realizarán con tu única línea! – neckTwi

Cuestiones relacionadas