Pregunta

Recientemente me encontré con algunas funciones donde se puede pasar múltiples enumeraciones de esta manera:

myFunction(One | Two);

Dado que creo que esta es una manera muy elegante Traté de poner en práctica algo así a mí mismo:

void myFunction(int _a){
    switch(_a){
        case One:
            cout<<"!!!!"<<endl;
            break;
        case Two:
            cout<<"?????"<<endl;
            break;
    }
}

Ahora si trato de llamar a la función con un | Dos, quiero que ambos casos interruptor consiguen llamados. No soy muy bueno con los operadores binarios, así que realmente no sé qué hacer. Cualquier idea sería grande!

Gracias!

¿Fue útil?

Solución

Para que usted tiene que hacer enumeraciones como:

enum STATE {
  STATE_A = 1,
  STATE_B = 2,
  STATE_C = 4
};

es decir. valor del elemento de enumeración debe ser en potencia de 2 para seleccionar caso válido o si la declaración.

Así que cuando haces gusto:

void foo( int state) {

  if ( state & STATE_A ) {
    //  do something 
  }

  if ( state & STATE_B ) {
    //  do something 
  }

  if ( state & STATE_C ) {
    //  do something 
  }   
}

int main() {
  foo( STATE_A | STATE_B | STATE_C);
}

Otros consejos

operadores

bit a bit comportan bien únicamente con potencias de 2:

  0010
| 0100
------
  0110  // both bits are set


  0110
& 0100
------
  0100  // nonzero, i.e. true: the flag is set

Si intenta hacer lo mismo con un número arbitrario, que obtendrá resultados inesperados:

  0101  // 5
| 1100  // 12
------
  1101  // 13

que contiene los posibles números (arbitrarias) como banderas conjunto: 0001 (1), 0100 (4), 0101 (5), 1000 (8), 1001 (9), 1100 (12), 1101 (13)

Así que en lugar de dar dos opciones, que acaba de dar a seis.

Por lo general, los argumentos que se combinan de esta manera son banderas (un valor de un solo bit) con un valor decimal de 1, 2, 4, 8, etc. Suponiendo que uno y dos siguen esta regla, no se puede utilizar un conmutador para comprobar si ambos. Interruptores sólo siguen un camino. Su argumento combinado no es igual a uno o dos, sino una combinación de ellos (1 | 2 == 3). Usted puede comprobar para ver si uno o dos se pone de esta manera:

if (_a & One)
{

}
if (_a & Two)
{

}

Recuerde que una enumeración estándar sin valores explícitos se acaba de contar hacia arriba, no utilice el siguiente bit. Si su próxima valor definido es de tres, es probable igual a 3, que no es un valor de un solo bit, y luego actuar como si hubiera pasado las dos banderas (One | Dos) a la función. Tendrá que establecer los valores de la enumeración mismo.

Debe dividir los posibles "tokens" (no se solapan, por supuesto ... utilizar potencia de 2):

if (_a & One) { ... }

No es elegante realmente hace lo que quiere con 1 instrucción switch: dividir el uso de declaraciones if

.

Usted es mejor hacerlo con un conjunto de instrucciones if ...

es decir,

if ( _a & ONE )
{
   // Do stuff.
}
if ( _a & TWO )
{
  // Do other stuff.
}

Edit: También puede hacerlo en una sentencia switch, pero sería una pesadilla. Youd necesita algo como esto

switch( _a )
{
case ONE:
   // Handle ONE.
   break;

case TWO:
   // Handle TWO.
   break;

case ONE | TWO:
   // Handle ONE.
   // Handle TWO.
   break;
};

Su relativamente cuerda por sólo 2 opciones, pero una vez que llegue más que eso se empieza a hinchar fuera de control. Si usted tiene de 32 opciones que tendría una sentencia switch que sería poco probable que quepa en cualquier máquina. Todo en el "si" la solución es mucho más limpio y más sano:)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top