Zoeken…


Basis opsomming

Met standaardtellingen kunnen gebruikers een nuttige naam opgeven voor een reeks gehele getallen. De namen worden gezamenlijk aangeduid als opsommers. Een opsomming en de bijbehorende opsommers zijn als volgt gedefinieerd:

enum myEnum
{
    enumName1,
    enumName2,
};

Een opsomming is een type dat verschilt van alle andere typen. In dit geval is de naam van dit type myEnum . Van dit soort objecten wordt verwacht dat ze de waarde van een teller binnen de opsomming aannemen.

De opsommers die binnen de opsomming zijn opgegeven, zijn constante waarden van het type opsomming. Hoewel de opsommers binnen het type worden gedeclareerd, is de scope-operator :: niet nodig om toegang te krijgen tot de naam. Dus de naam van de eerste teller is enumName1 .

C ++ 11

De scope-operator kan optioneel worden gebruikt om toegang te krijgen tot een teller in een opsomming. Dus enumName1 kan ook worden gespeld als myEnum::enumName1 .

Tellers krijgen hele waarden toegewezen die beginnen bij 0 en oplopen met 1 voor elke teller in een opsomming. Dus in het bovenstaande geval heeft enumName1 de waarde 0, en enumName2 heeft de waarde 1.

Tellers kunnen ook een specifieke waarde krijgen van de gebruiker; deze waarde moet een integrale constante uitdrukking zijn. Tellers waarvan de waarden niet expliciet worden opgegeven, moeten hun waarde instellen op de waarde van de vorige 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
};

Opsomming in schakeluitspraken

Een veelgebruikt gebruik voor tellers is voor schakelinstructies en ze verschijnen daarom meestal in statusmachines. Een handig kenmerk van schakelinstructies met opsommingen is dat als er geen standaardinstructie voor de schakeloptie is opgenomen en niet alle waarden van het opsommingsteken zijn gebruikt, de compiler een waarschuwing geeft.

enum State {
    start,
    middle,
    end
};

...

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

Iteratie over een opsomming

Er is geen ingebouwd om over opsomming te herhalen.

Maar er zijn verschillende manieren

  • voor enum met alleen opeenvolgende waarden:

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

met enum class moet operator ++ worden geïmplementeerd:

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;
}
  • een container gebruiken als 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();
    

    en toen

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

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

    en toen

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

Scoped enums

C ++ 11 introduceert wat bekend staat als scoped enums . Dit zijn opsommingen waarvan de leden moeten zijn gekwalificeerd met enumname::membername . Scoped-enums worden gedeclareerd met behulp van de syntaxis van de enum class . Om bijvoorbeeld de kleuren in een regenboog op te slaan:

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

Toegang krijgen tot een specifieke kleur:

rainbow r = rainbow::INDIGO;

enum class kunnen niet impliciet worden omgezet in int zonder cast. Dus int x = rainbow::RED is ongeldig.

Met Scoped-enums kunt u ook het onderliggende type opgeven, het type dat wordt gebruikt om een lid te vertegenwoordigen. Standaard is dit int . In een Tic-Tac-Toe-spel kun je het stuk opslaan als

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

Zoals je misschien ziet, kan enum s een komma achter het laatste lid hebben.

Enum forward-verklaring in C ++ 11

Scoped-opsommingen:

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

Unscoped-opsommingen:

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

Een uitgebreid voorbeeld van meerdere bestanden vindt u hier: Voorbeeld van een blinde fruithandelaar



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow