Sou um iniciante em programação C ++.
Hoje me deparei com um novo tópico: fortemente tipado enum
. Pesquisei um pouco, mas até agora não consigo descobrir por que precisamos disso e para que serve?
Por exemplo, se tivermos:
enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/
Por que precisamos escrever:
enum class xyz{a, b, c};
O que estamos tentando fazer aqui? Minha dúvida mais importante é como usá-lo. Você poderia dar um pequeno exemplo, que me faça entender.
enum class Colours
eenum class Fruits
. Porque quando escrevi o código no VS 2010. Ele lança um erro"expects a defination or a tag name"
emclass
.Há um bom artigo sobre enums nesta página da IBM , é muito detalhado e bem escrito. Aqui estão alguns pontos importantes em poucas palavras:
Os enums com escopo resolvem a maioria das limitações incorridas por enums regulares: segurança de tipo completa, tipo subjacente bem definido, problemas de escopo e declaração de encaminhamento.
fonte
Os valores de
enum class
é realmente do tipoenum class
, nãounderlying_type
como para C-enums.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);
fonte
As classes enum ("novos enums", "enums fortes") abordam três problemas com enumerações C ++ tradicionais:
enums
implicitamente converter emint
, causando erros quando alguém não deseja que uma enumeração atue como um inteiro.enums
exportar seus enumeradores para o escopo circundante, causando conflitos de nome.enum
não pode ser especificado, causando confusão, problemas de compatibilidade e impossibilitando a declaração de encaminhamento.enum class
("enums fortes") são fortemente tipados e com escopo definido: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
Conforme mostrado, enums tradicionais funcionam como de costume, mas agora você pode se qualificar opcionalmente com o nome do enum.
Os novos enums são "classe enum" porque combinam aspectos de enumerações tradicionais (valores de nomes) com aspectos de classes (membros com escopo definido e ausência de conversões).
Ser capaz de especificar o tipo subjacente permite uma interoperabilidade mais simples e tamanhos garantidos de enumerações:
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
Ele também permite a declaração de enums:
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
O tipo subjacente deve ser um dos tipos inteiros assinados ou não assinados; o padrão é
int
.Na biblioteca padrão, as
enum
classes são usadas 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 };
Vários deles têm operadores, conforme
==
definido.fonte
Escopo Enum
As enumerações exportam seus enumeradores para o escopo circundante. Isso tem duas desvantagens. Em primeiro lugar, pode levar a conflitos de nome, se dois enumeradores em enums diferentes declarados no mesmo escopo tiverem o mesmo nome; segundo, não é possível usar um enumerador com um nome totalmente qualificado, incluindo o nome enum.
enum ESet {a0, a, a1, b1, c3}; enum EAlpha{a, b, c} select = ESet::a; // error select = a; // is ambigious
fonte