Soy un principiante en programación C ++.
Hoy me encuentro con un nuevo tema: fuertemente tipado enum
. Lo he investigado un poco, pero hasta ahora no he podido averiguar por qué lo necesitamos y para qué sirve.
Por ejemplo si tenemos:
enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/
Por qué necesitamos escribir:
enum class xyz{a, b, c};
¿Qué estamos tratando de hacer aquí? Mi duda más importante es cómo usarlo. ¿Podría dar un pequeño ejemplo que me haga entender?
enum class Colours
yenum class Fruits
. Porque cuando escribí el código en VS 2010. arroja un error"expects a defination or a tag name"
debajoclass
.Hay un buen artículo sobre enumeraciones en esta página de IBM , es muy detallado y está bien escrito. Aquí hay algunos puntos importantes en pocas palabras:
Las enumeraciones con ámbito resuelven la mayoría de las limitaciones en las que incurren las enumeraciones regulares: seguridad de tipo completa, tipo subyacente bien definido, problemas de alcance y declaración de reenvío.
fuente
Los valores de
enum class
son realmente de tipoenum class
, nounderlying_type
como para C-enumeraciones.enum xyz { a, b, c}; enum class xyz_c { d, f, e }; void f(xyz x) { } void f_c(xyz_c x) { } // OK. f(0); // OK for C++03 and C++11. f(a); // OK with C++11. f(xyz::a); // ERROR. f_c(0); // OK. f_c(xyz_c::d);
fuente
Las clases de enumeración ("enumeraciones nuevas", "enumeraciones fuertes") abordan tres problemas con las enumeraciones tradicionales de C ++:
enums
implícitamente se convierte enint
, provocando errores cuando alguien no quiere que una enumeración actúe como un número entero.enums
exportan sus enumeradores convencionales al ámbito circundante, lo que provoca conflictos de nombres.enum
no se puede especificar, lo que genera confusión, problemas de compatibilidad y hace imposible la declaración hacia adelante.enum class
("enumeraciones fuertes") están fuertemente tipados y con alcance:enum Alert { green, yellow, orange, red }; // traditional enum enum class Color { red, blue }; // scoped and strongly typed enum // no export of enumerator names into enclosing scope // no implicit conversion to int enum class TrafficLight { red, yellow, green }; Alert a = 7; // error (as ever in C++) Color c = 7; // error: no int->Color conversion int a2 = red; // ok: Alert->int conversion int a3 = Alert::red; // error in C++98; ok in C++11 int a4 = blue; // error: blue not in scope int a5 = Color::blue; // error: not Color->int conversion Color a6 = Color::blue; // ok
Como se muestra, las enumeraciones tradicionales funcionan como de costumbre, pero ahora puede calificar opcionalmente con el nombre de la enumeración.
Las nuevas enumeraciones son "clase de enumeración" porque combinan aspectos de enumeraciones tradicionales (valores de nombres) con aspectos de clases (miembros de ámbito y ausencia de conversiones).
Ser capaz de especificar el tipo subyacente permite una interoperabilidad más simple y tamaños garantizados de enumeraciones:
enum class Color : char { red, blue }; // compact representation enum class TrafficLight { red, yellow, green }; // by default, the underlying type is int enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E? // (whatever the old rules say; // i.e. "implementation defined") enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // now we can be specific
También permite la declaración hacia adelante de enumeraciones:
enum class Color_code : char; // (forward) declaration void foobar(Color_code* p); // use of forward declaration // ... enum class Color_code : char { red, yellow, green, blue }; // definition
El tipo subyacente debe ser uno de los tipos enteros con o sin signo; el predeterminado es
int
.En la biblioteca estándar, las
enum
clases se utilizan para:<system_error>
:enum class errc
;<memory>
:enum class pointer_safety { relaxed, preferred, strict };
<iosfwd>
:enum class io_errc { stream = 1 };
<future>
:enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
Varios de estos tienen operadores, como los
==
definidos.fuente
Alcance de la enumeración
Las enumeraciones exportan sus enumeradores al ámbito circundante. Esto tiene dos inconvenientes. Primero, puede dar lugar a conflictos de nombres, si dos enumeradores en diferentes enumeraciones declaradas en el mismo ámbito tienen el mismo nombre; en segundo lugar, no es posible utilizar un enumerador con un nombre completo, incluido el nombre de enumeración.
enum ESet {a0, a, a1, b1, c3}; enum EAlpha{a, b, c} select = ESet::a; // error select = a; // is ambigious
fuente