Jestem początkującym w programowaniu w C ++.
Dziś trafiłem na nowy temat: mocno wpisany enum
. Trochę to zbadałem, ale do tej pory nie jestem w stanie dowiedzieć się, dlaczego tego potrzebujemy i jaki jest pożytek z tego samego?
Na przykład, jeśli mamy:
enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/
Dlaczego musimy pisać:
enum class xyz{a, b, c};
Co my tu próbujemy zrobić? Moja najważniejsza wątpliwość dotyczy tego, jak go używać. Czy mógłbyś podać mały przykład, który pozwoli mi zrozumieć.
enum class Colours
ienum class Fruits
. Bo kiedy pisałem kod w VS 2010. zgłasza błąd"expects a defination or a tag name"
mocyclass
.Na tej stronie IBM jest dobry artykuł o wyliczeniach , jest bardzo szczegółowy i dobrze napisany. Oto kilka ważnych punktów w pigułce:
Wyliczenia o określonym zakresie rozwiązują większość ograniczeń występujących w zwykłych wyliczeniach: pełne bezpieczeństwo typu, dobrze zdefiniowany typ podstawowy, problemy z zakresem i deklaracja do przodu.
źródło
Wartości
enum class
są naprawdę typuenum class
, a nieunderlying_type
dla wyliczeń C.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);
źródło
Klasy wyliczeniowe („nowe wyliczenia”, „silne wyliczenia”) rozwiązują trzy problemy z tradycyjnymi wyliczeniami w języku C ++:
enums
niejawnie konwertuj naint
, powodując błędy, gdy ktoś nie chce, aby wyliczenie działało jak liczba całkowita.enums
eksportują swoje moduły wyliczające do otaczającego zakresu, powodując konflikty nazw.enum
Nie można określić bazowego typu an , co powoduje zamieszanie, problemy ze zgodnością i uniemożliwia przekazanie deklaracji.enum class
(„silne wyliczenia”) są silnie wpisane i mają określony zakres: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
Jak pokazano, tradycyjne wyliczenia działają jak zwykle, ale można teraz opcjonalnie kwalifikować się przy użyciu nazwy wyliczenia.
Nowe wyliczenia są „klasami wyliczeń”, ponieważ łączą aspekty tradycyjnych wyliczeń (wartości nazw) z aspektami klas (elementy członkowskie o określonym zakresie i brak konwersji).
Możliwość określenia podstawowego typu pozwala na prostszą interoperacyjność i gwarantowane rozmiary wyliczeń:
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
Umożliwia również przekazywanie do przodu wyliczeń:
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
Typ bazowy musi być jednym z typów całkowitych ze znakiem lub bez znaku; wartość domyślna to
int
.W bibliotece standardowej
enum
klasy służą do:<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 };
Kilka z nich ma operatory, takie jak
==
zdefiniowano.źródło
Enum Scope
Wyliczenia eksportują swoje moduły wyliczające do otaczającego zakresu. Ma to dwie wady. Po pierwsze, może prowadzić do konfliktów nazw, jeśli dwa wyliczacze w różnych wyliczeniach zadeklarowanych w tym samym zakresie mają tę samą nazwę; po drugie, nie jest możliwe użycie modułu wyliczającego z w pełni kwalifikowaną nazwą, w tym nazwą wyliczenia.
enum ESet {a0, a, a1, b1, c3}; enum EAlpha{a, b, c} select = ESet::a; // error select = a; // is ambigious
źródło