2011-07-06 7 views
7

Con las siguientes C++ definiciones:¿Por qué no puedo asignar el elemento enum incorrecto, pero puedo compararlo con el elemento enum incorrecto?

enum EnumA { 
    EA_Element = 1 
}; 

enum EnumB { 
    EB_Element = 10 
}; 

el siguiente código no se compilará y que sólo tiene sentido:

EnumA variable; 
variable = EB_Element; // won't compile 

pero el siguiente código se compila:

EnumA variable = EA_Element; 
if(variable == EB_Element) { //will compile 
} 

aunque no puede tener ningún sentido: se enumeran diferentes enumeraciones y es probable que ese código sea erróneo.

¿Por qué estas situaciones aparentemente idénticas se manejan de manera diferente en C++?

+2

no debería ser el caso willf compilar ser: 'variable = EB_Element;'? – Donotalo

+0

@Donotalo: Reparado, gracias. – sharptooth

Respuesta

4

Ese argumento es correcto, ya que he visto que cualquier tipo de enum se puede comparar con cualquier tipo de enum. Esto se debe a que, para fines de comparación, las variables enum y los valores deben ser convertidos a tipo integral (como int). Cierto compilador do raise the warning.

Tal argumento puede verdad para la comparación entre unsigned int, int, size_t etc., pero puede ser que todos ellos se limitan a una advertencia del compilador por la misma razón.

Sin embargo, este problema se trata en C++ 0x con enum class (no han cambiado el comportamiento existente enum para mantener la compatibilidad).

2

No es que sea imposible, es solo que su compilador los considera dos tipos de datos diferentes cuando ambos son enteros. Entonces, un simple encasillado resolvería el problema.

EnumA variable; 
variable = (EnumA)EB_Element; 
+1

el yeso no es necesario. – Donotalo

+0

No veo por qué no. – Drake

+0

mi comentario fue antes de editar. – Donotalo

6

Se compilará porque "por enumeraciones predeterminadas se convierten en enteros para operaciones aritméticas". (En: El lenguaje de programación C++)

1

¡Bienvenido a C++!

por algo aún más divertido probar esto:

#include <string> 

int main(int argc, const char *argv[]) 
{ 
    std::string s; 
    s = 3.141592654; 
    return 0; 
} 

¿Por qué se compilan? La razón es que las reglas del lenguaje lo dicen.

En este caso funky, la explicación "oficial" sobre por qué compila este ejemplo es que parecía correcto permitir std::string::operator+=(char) (IMO correcto y lógico desde un punto de vista pragmático) y "por lo tanto" también asignación de char (IMO ilógico no -sequitur). Pero los caracteres son ints (ilógico, pero el patrimonio C) y los dobles se pueden convertir implícitamente en enteros (ilógico, pero el patrimonio C). Por lo tanto, en C++ es ilógico (pero legal) asignar un doble a una cadena.

No te sientas mal si no lo sabías, la mayoría de los programadores de C++ que he mostrado están desconcertados por la razón por la cual un disparate compila y piensa en otros errores semánticos o de compilación.

En el caso de su pregunta, la razón es que las enumeraciones son como en algún contexto (probablemente debido a la herencia en casos de uso) pero no como en otros contextos. Es absurdo, pero es lo que exige el estándar.

Si se siente incómodo con esta aparente ausencia de lógica, recuerde que C++ es principalmente el resultado de una larga historia e incluso de un comité (!) Así que la lógica realmente no tiene mucho que ver con eso. Esto también implica que uno no puede usar la lógica para evitar el estudio de C++: no importa cuán inteligente sea usted, no hay manera de que adivine los accidentes históricos y las decisiones políticas de los comités.

La alta complejidad de C++, esta ausencia de lógica en muchos lugares y la presencia de undefined behavior daemons en lugar de runtime error angels es también lo que IMO básicamente descarta aprender C++ por experimentación.

Elija un buen libro (o unos pocos) y léalo (les) de principio a fin ... desafortunadamente no hay otra manera. Mis sugerencias son: "El lenguaje de programación C++" (Stroustrup), "C++ efectivo" & "C++ más efectivo" (Meyers), "Preguntas frecuentes sobre C++" (Cline/Lomow/Girou).

C++ es una arma bastante poderosa y agradable de poseer, pero acércala desde el lado equivocado y puede convertirse en la peor de tus pesadillas. Asumir que puedes entenderlo simplemente usando lógica es un enfoque equivocado (y no porque tu lógica sea débil, sino porque C++ no es solo lógica).

+0

-1, no respondió la pregunta, el ejemplo no tiene relación con la pregunta y la lógica tiene todo que ver con el motivo por el que compila el ejemplo. –

+0

La respuesta ya estaba ahí para ambos casos (porque el estándar lo dice) y pensé que era importante advertir sobre el error de sobreestimar el poder de la lógica al entender C++. De todos modos, he agregado una explicación más detallada si esto te hace sentir mejor. Me gusta C++ pero si dices que es un lenguaje lógico, entonces IMO todavía estás en la etapa fanboy. Vuelve después de escribir unas pocas cientos de miles de líneas de código C++ en funcionamiento y hablemos de nuevo. – 6502

+0

Oh, he escrito más que mi parte justa de C++, y no soy fanático. En cuanto a 's = 3.14159;' sí, es feo. Sin embargo, cada paso de punto flotante a entero a char a asignación es bastante correcto. Usted acepta 's + = some_char;' está bien. Tenga en cuenta que 's + = some_char;' tiene el mismo efecto que 's = some_char;' en el caso de una cadena vacía, por lo que proporcionar 'operator = (char)' tiene mucho sentido. Su ejemplo ejemplifica por qué las organizaciones hacen revisiones de código. El hecho de que un trozo de código sea perfectamente válido no significa que no huela hasta el cielo. –

Cuestiones relacionadas