usar sirven que programacion para los enum diagrama como clases clase c++ class enums c++-faq

c++ - sirven - ¿Por qué es la clase enum preferida sobre enumeración simple?



para que sirven los enum (6)

De las preguntas frecuentes sobre C ++ 11 de Bjarne Stroustrup :

La enum class es ("new enums", "strong enums") resuelve tres problemas con las enumeraciones tradicionales de C ++:

  • las enumeraciones convencionales se convierten implícitamente a int, causando errores cuando alguien no quiere que una enumeración actúe como un entero.
  • Enums convencionales exportan sus enumeradores al ámbito circundante, causando choques de nombre.
  • el tipo subyacente de una enum no se puede especificar, causando confusión, problemas de compatibilidad y hace imposible la declaración en adelante.

Las nuevas enumeraciones son "enum class" porque combinan aspectos de enumeraciones tradicionales (nombres de valores) con aspectos de clases (miembros con alcance y ausencia de conversiones).

Entonces, como lo mencionaron otros usuarios, los "enums fuertes" harían que el código sea más seguro.

El tipo subyacente de una enum "clásica" será un tipo entero lo suficientemente grande como para ajustarse a todos los valores de la enum ; esto suele ser un int . Además, cada tipo enumerado será compatible con char o un tipo entero con signo / sin signo.

Esta es una descripción amplia de lo que debe ser un tipo subyacente de enum , por lo que cada compilador tomará sus propias decisiones sobre el tipo subyacente de la enum clásica y, a veces, el resultado podría ser sorprendente.

Por ejemplo, he visto un código como este muchas veces:

enum E_MY_FAVOURITE_FRUITS { E_APPLE = 0x01, E_WATERMELON = 0x02, E_COCONUT = 0x04, E_STRAWBERRY = 0x08, E_CHERRY = 0x10, E_PINEAPPLE = 0x20, E_BANANA = 0x40, E_MANGO = 0x80, E_MY_FAVOURITE_FRUITS_FORCE8 = 0xFF // ''Force'' 8bits, how can you tell? };

En el código anterior, algunos programadores ingenuos están pensando que el compilador almacenará los valores E_MY_FAVOURITE_FRUITS en un tipo sin signo de 8 bits ... pero no hay garantía al respecto: el compilador puede elegir caracteres unsigned char o int o short , cualquiera de esos tipos es grande suficiente para adaptarse a todos los valores vistos en la enum . Agregar el campo E_MY_FAVOURITE_FRUITS_FORCE8 es una carga y no obliga al compilador a hacer ningún tipo de elección sobre el tipo subyacente de la enum .

Si hay algún fragmento de código que se basa en el tamaño del tipo y / o asume que E_MY_FAVOURITE_FRUITS sería de algún ancho (por ejemplo: rutinas de serialización), este código podría comportarse de alguna manera extraña dependiendo de los pensamientos del compilador.

Y para empeorar las cosas, si algún compañero de trabajo agrega descuidadamente un nuevo valor a nuestra enum :

E_DEVIL_FRUIT = 0x100, // New fruit, with value greater than 8bits

¡El compilador no se queja! Simplemente redimensiona el tipo para que se ajuste a todos los valores de la enum (asumiendo que el compilador estaba usando el tipo más pequeño posible, lo cual es una suposición que no podemos hacer). Esta adición simple y descuidada a la enum podría romper con sutileza el código relacionado.

Dado que C ++ 11 es posible especificar el tipo subyacente para enum y enum class (gracias rdb ) por lo que este problema se resuelve de forma rdb :

enum class E_MY_FAVOURITE_FRUITS : unsigned char { E_APPLE = 0x01, E_WATERMELON = 0x02, E_COCONUT = 0x04, E_STRAWBERRY = 0x08, E_CHERRY = 0x10, E_PINEAPPLE = 0x20, E_BANANA = 0x40, E_MANGO = 0x80, E_DEVIL_FRUIT = 0x100, // Warning!: constant value truncated };

Especificando el tipo subyacente si un campo tiene una expresión fuera del rango de este tipo, el compilador se quejará en lugar de cambiar el tipo subyacente.

Creo que esta es una buena mejora de seguridad.

Entonces, ¿ por qué se prefiere la clase enum en lugar de enumeración simple? Si podemos elegir el tipo subyacente para las enum class con ámbito ( enum class ) y sin enumerar ( enum ), ¿qué otra cosa hace que la enum class sea ​​una mejor opción ?:

  • No se convierten implícitamente a int .
  • No contaminan el espacio de nombres circundante.
  • Pueden ser declarados hacia adelante.

Escuché a algunas personas recomendar el uso de clases de enumeración en C ++ debido a su tipo de seguridad .

Pero, ¿qué significa esto realmente?


Debido a que, como se dijo en otras respuestas, la clase enumeración no se puede convertir implícitamente a int / bool, también ayuda a evitar el código con errores como:

enum MyEnum { Value1, Value2, }; ... if (var == Value1 || Value2) // Should be "var == Value2" no error/warning


La ventaja básica de usar enum class sobre las enumeraciones normales es que puede tener las mismas variables de enumeración para 2 enumeraciones diferentes y aún así puede resolverlas (lo cual ha sido mencionado como de tipo seguro por OP)

Por ejemplo:

enum class Color1 { red, green, blue }; //this will compile enum class Color2 { red, green, blue }; enum Color1 { red, green, blue }; //this will not compile enum Color2 { red, green, blue };

En cuanto a las enumeraciones básicas, el compilador no podrá distinguir si el red se Color1 al tipo Color1 o Color2 como en la siguiente declaración.

enum Color1 { red, green, blue }; enum Color2 { red, green, blue }; int x = red; //Compile time error(which red are you refering to??)


Las enumeraciones se utilizan para representar un conjunto de valores enteros.

La palabra clave de class después de la enum especifica que la enumeración está fuertemente tipada y sus enumeradores tienen un alcance. De esta manera las clases de enum previenen el mal uso accidental de las constantes.

Por ejemplo:

enum class Animal{Dog, Cat, Tiger}; enum class Pets{Dog, Parrot};

Aquí no podemos mezclar valores de animales y mascotas.

Animal a = Dog; // Error: which DOG? Animal a = Pets::Dog // Pets::Dog is not an Animal


C ++ 11 preguntas frecuentes a continuación puntos:

las enumeraciones convencionales se convierten implícitamente a int, causando errores cuando alguien no quiere que una enumeración actúe como un entero.

enum color { Red, Green, Yellow }; enum class NewColor { Red_1, Green_1, Yellow_1 }; int main() { //! Implicit conversion is possible int i = Red; //! Need enum class name followed by access specifier. Ex: NewColor::Red_1 int j = Red_1; // error C2065: ''Red_1'': undeclared identifier //! Implicit converison is not possible. Solution Ex: int k = (int)NewColor::Red_1; int k = NewColor::Red_1; // error C2440: ''initializing'': cannot convert from ''NewColor'' to ''int'' return 0; }

Enums convencionales exportan sus enumeradores al ámbito circundante, causando choques de nombre.

// Header.h enum vehicle { Car, Bus, Bike, Autorickshow }; enum FourWheeler { Car, // error C2365: ''Car'': redefinition; previous definition was ''enumerator'' SmallBus }; enum class Editor { vim, eclipes, VisualStudio }; enum class CppEditor { eclipes, // No error of redefinitions VisualStudio, // No error of redefinitions QtCreator };

El tipo subyacente de una enumeración no se puede especificar, causando confusión, problemas de compatibilidad y hace imposible la declaración en adelante.

// Header1.h #include <iostream> using namespace std; enum class Port : unsigned char; // Forward declare class MyClass { public: void PrintPort(enum class Port p); }; void MyClass::PrintPort(enum class Port p) { cout << (int)p << endl; }

.

// Header.h enum class Port : unsigned char // Declare enum type explicitly { PORT_1 = 0x01, PORT_2 = 0x02, PORT_3 = 0x04 };

.

// Source.cpp #include "Header1.h" #include "Header.h" using namespace std; int main() { MyClass m; m.PrintPort(Port::PORT_1); return 0; }


C ++ tiene dos tipos de enum :

  1. enum class es
  2. enum simple

Aquí hay un par de ejemplos de cómo declararlos:

enum class Color { red, green, blue }; // enum class enum Animal { dog, cat, bird, human }; // plain enum

¿Cuál es la diferencia entre dos?

  • enum class es: los nombres de los enumeradores son locales a la enumeración y sus valores no se convierten implícitamente a otros tipos (como otra enum o int )

  • Enumeración simple s: donde los nombres de los enumeradores están en el mismo ámbito que la enumeración y sus valores se convierten implícitamente en números enteros y otros tipos

Ejemplo:

enum Color { red, green, blue }; // plain enum enum Card { red_card, green_card, yellow_card }; // another plain enum enum class Animal { dog, deer, cat, bird, human }; // enum class enum class Mammal { kangaroo, deer, human }; // another enum class void fun() { // examples of bad use of plain enums: Color color = Color::red; Card card = Card::green_card; int num = color; // no problem if (color == Card::red_card) // no problem (bad) cout << "bad" << endl; if (card == Color::green) // no problem (bad) cout << "bad" << endl; // examples of good use of enum classes (safe) Animal a = Animal::deer; Mammal m = Mammal::deer; int num2 = a; // error if (m == a) // error (good) cout << "bad" << endl; if (a == Mammal::deer) // error (good) cout << "bad" << endl; }

Conclusión:

enum class deben ser preferidas porque causan menos sorpresas que podrían llevar a errores.