Szukaj…


Podstawowa deklaracja wyliczenia

Standardowe wyliczenia pozwalają użytkownikom zadeklarować użyteczną nazwę dla zestawu liczb całkowitych. Nazwy są łącznie nazywane licznikami. Wyliczenie i powiązane z nim elementy wyliczające są zdefiniowane w następujący sposób:

enum myEnum
{
    enumName1,
    enumName2,
};

Wyliczenie to typ , który różni się od wszystkich innych typów. W tym przypadku nazwa tego typu to myEnum . Oczekuje się, że obiekty tego typu przyjmą wartość modułu wyliczającego w ramach wyliczenia.

Elementy wyliczające zadeklarowane w ramach wyliczenia są stałymi wartościami typu wyliczenia. Chociaż wyliczacze są zadeklarowane w ramach typu, operator zasięgu :: nie jest potrzebny do uzyskania dostępu do nazwy. Tak więc nazwa pierwszego modułu wyliczającego to enumName1 .

C ++ 11

Operator zakresu można opcjonalnie wykorzystać do uzyskania dostępu do modułu wyliczającego w ramach wyliczenia. Tak więc enumName1 można również przeliterować myEnum::enumName1 .

Modułom obliczającym są przypisywane wartości całkowite zaczynające się od 0 i wzrastające o 1 dla każdego modułu wyliczającego w wyliczeniu. W powyższym przypadku enumName1 ma wartość 0, a enumName2 ma wartość 1.

Użytkownikowi można również przypisać określoną wartość do liczników; ta wartość musi być integralnym stałym wyrażeniem. Wyliczacze, których wartości nie są wyraźnie podane, będą mieli wartość ustawioną na wartość poprzedniego wyliczacza + 1.

enum myEnum
{
    enumName1 = 1, // value will be 1
    enumName2 = 2, // value will be 2
    enumName3,     // value will be 3, previous value + 1
    enumName4 = 7, // value will be 7
    enumName5,     // value will be 8
    enumName6 = 5, // value will be 5, legal to go backwards
    enumName7 = 3, // value will be 3, legal to reuse numbers
    enumName8 = enumName4 + 2, // value will be 9, legal to take prior enums and adjust them
};

Wyliczenie w instrukcjach switch

Częstym zastosowaniem enumeratorów są instrukcje przełączników, dlatego często pojawiają się w automatach stanów. W rzeczywistości użyteczną cechą instrukcji switch z wyliczeniami jest to, że jeśli nie zostanie dołączona żadna instrukcja domyślna dla przełącznika i nie zostaną użyte wszystkie wartości wyliczenia, kompilator wyda ostrzeżenie.

enum State {
    start,
    middle,
    end
};

...

switch(myState) {
    case start:
       ...
    case middle:
       ...
} // warning: enumeration value 'end' not handled in switch [-Wswitch]

Iteracja przez wyliczenie

Nie ma wbudowanego mechanizmu iteracji po wyliczeniu.

Ale jest kilka sposobów

  • dla enum tylko z kolejnymi wartościami:

    enum E {
        Begin,
        E1 = Begin,
        E2,
        // ..
        En,
        End
    };
    
    for (E e = E::Begin; e != E::End; ++e) {
        // Do job with e
    }
    
C ++ 11

z enum class operator ++ musi zostać zaimplementowany:

E& operator ++ (E& e)
{
    if (e == E::End) {
        throw std::out_of_range("for E& operator ++ (E&)");
    }
    e = E(static_cast<std::underlying_type<E>::type>(e) + 1);
    return e;
}
  • używając kontenera jako std::vector

    enum E {
        E1 = 4,
        E2 = 8,
        // ..
        En
    };
    
    std::vector<E> build_all_E()
    {
        const E all[] = {E1, E2, /*..*/ En};
        
        return std::vector<E>(all, all + sizeof(all) / sizeof(E));
    }
    
    std::vector<E> all_E = build_all_E();
    

    i wtedy

    for (std::vector<E>::const_iterator it = all_E.begin(); it != all_E.end(); ++it) {
        E e = *it;
        // Do job with e;
    }
    
C ++ 11
  • lub std::initializer_list i prostsza składnia:

    enum E {
        E1 = 4,
        E2 = 8,
        // ..
        En
    };
    
    constexpr std::initializer_list<E> all_E = {E1, E2, /*..*/ En};
    

    i wtedy

    for (auto e : all_E) {
        // Do job with e
    }
    

Wyliczenia z zakresu

C ++ 11 wprowadza tak zwane wyliczenia zakresowe . Są to wyliczenia, których członkowie muszą być kwalifikowani przy pomocy enumname::membername . Wyliczenia zakresowe są deklarowane przy użyciu składni enum class . Na przykład, aby zapisać kolory w tęczy:

enum class rainbow {
    RED,
    ORANGE,
    YELLOW,
    GREEN,
    BLUE,
    INDIGO,
    VIOLET
};

Aby uzyskać dostęp do określonego koloru:

rainbow r = rainbow::INDIGO;

enum class nie można domyślnie konwertować na int bez rzutowania. Więc int x = rainbow::RED jest niepoprawny.

Wyliczenia zakresowe pozwalają również określić typ bazowy , który jest typem używanym do reprezentowania członka. Domyślnie jest to int . W grze Kółko i krzyżyk możesz przechowywać element jako

enum class piece : char {
    EMPTY = '\0',
    X = 'X',
    O = 'O',
};

Jak możesz zauważyć, enum mogą mieć przecinek końcowy po ostatnim elemencie.

Deklaracja przekazania w trybie enum w C ++ 11

Wyliczenia o zasięgu:

...
enum class Status; // Forward declaration 
Status doWork(); // Use the forward declaration
...
enum class Status { Invalid, Success, Fail };
Status doWork() // Full declaration required for implementation
{
    return Status::Success;
}    

Nieokreślone wyliczenia:

...
enum Status: int; // Forward declaration, explicit type required
Status doWork(); // Use the forward declaration
...
enum Status: int{ Invalid=0, Success, Fail }; // Must match forward declare type
static_assert( Success == 1 );

Szczegółowy przykład wielu plików można znaleźć tutaj: Przykład sprzedawcy ślepych owoców



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow