Sök…


Grundläggande uppräkning av uppräkning

Standarduppräkningar tillåter användare att förklara ett användbart namn för en uppsättning heltal. Namnen kallas kollektivt som uppräknare. En uppräkning och dess tillhörande räknare definieras enligt följande:

enum myEnum
{
    enumName1,
    enumName2,
};

En uppräkning är en typ , en som skiljer sig från alla andra typer. I detta fall är namnet på denna typ myEnum . Objekt av denna typ förväntas anta värdet på en räknare inom uppräkningen.

De uppräknare som anges inom uppräkningen är konstanta värden av typen av uppräkningen. Även om uppräknare deklareras inom typen, behövs inte omfattningsoperatören :: för att få åtkomst till namnet. Så namnet på den första enumName1 är enumName1 .

C ++ 11

Omfångsoperatören kan valfritt användas för att komma åt en uppräknare inom en uppräkning. Så enumName1 kan också stavas myEnum::enumName1 .

Uppräknare tilldelas heltal med början från 0 och ökar med 1 för varje teller i en uppräkning. Så i ovanstående fall har enumName1 värdet 0, medan enumName2 har värdet 1.

Enumeratorer kan också tilldelas ett specifikt värde av användaren; detta värde måste vara ett integrerat konstant uttryck. Räknare som inte har uttryckligen tillhandahållit värden kommer att ha sitt värde inställt på värdet på föregående teller + 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
};

Uppräkning i switch-uttalanden

En vanlig användning för räknare är för switch-uttalanden och så de ofta visas i tillståndsmaskiner. I själva verket är en användbar funktion för switch-uttalanden med uppräkningar att om inget standarduttalande ingår för omkopplaren, och inte alla värden på enum har använts, kommer kompilatorn att ge en varning.

enum State {
    start,
    middle,
    end
};

...

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

Iteration över enum

Det finns inget inbyggt för att iterera över uppräkning.

Men det finns flera sätt

  • för enum med endast på varandra följande värden:

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

med enum class operator ++ implementeras:

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;
}
  • använder en behållare som 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();
    

    och då

    for (std::vector<E>::const_iterator it = all_E.begin(); it != all_E.end(); ++it) {
        E e = *it;
        // Do job with e;
    }
    
C ++ 11
  • eller std::initializer_list och en enklare syntax:

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

    och då

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

Scoped enums

C ++ 11 introducerar så kallade scoped-enums . Detta är uppräkningar vars medlemmar måste vara kvalificerade med enumname::membername . Omfattade enums deklareras med enum class syntax. För att till exempel lagra färgerna i en regnbåge:

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

Så här får du åtkomst till en specifik färg:

rainbow r = rainbow::INDIGO;

enum class es kan inte implicit konverteras till int utan rollspel. Så int x = rainbow::RED är ogiltig.

Omfattade enums tillåter dig också att ange den underliggande typen , som är den typ som används för att representera en medlem. Som standard är det int . I ett Tic-Tac-Toe-spel kan du lagra stycket som

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

Som du kanske märker, kan enum ha en efterföljande komma efter den sista medlemmen.

Enum framåtdeklaration i C ++ 11

Omfattade uppräkningar:

...
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;
}    

Obeskrivna uppräkningar:

...
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 );

Ett fördjupat exempel på flera filer kan hittas här: Exempel på handlare av blind frukt



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow