748 Stimmen

Warum wird die enum-Klasse der einfachen enum vorgezogen?

Ich habe gehört, dass einige Leute empfehlen, in C++ enum Klassen zu verwenden, wegen ihrer Typsicherheit.

Aber was bedeutet das wirklich?

11voto

Swapnil Punkte 1394

C++11 FAQ erwähnt die folgenden Punkte:

konventionelle Aufzählungstypen konvertieren implizit in int, was zu Fehlern führt, wenn jemand nicht möchte, dass eine Aufzählung als Ganzzahl fungiert.

enum Farbe
{
    Rot,
    Grün,
    Gelb
};

enum class NeueFarbe
{
    Rot_1,
    Grün_1,
    Gelb_1
};

int main()
{
    //! Implizite Konvertierung ist möglich
    int i = Rot;

    //! Benötigen Sie den Aufzählungstypen gefolgt von Zugriffsmodifizierer. Bsp: NeueFarbe::Rot_1
    int j = Rot_1; // Fehler C2065: 'Rot_1': nichtdeklarierter Bezeichner

    //! Implizite Konvertierung ist nicht möglich. Lösung Bsp: int k = (int)NeueFarbe::Rot_1;
    int k = NeueFarbe::Rot_1; // Fehler C2440: 'Initialisierung': Kann nicht von 'NeueFarbe' in 'int' konvertiert werden

    return 0;
}

Konventionelle Aufzählungstypen exportieren ihre Elemente in den umgebenden Bereich, was zu Namenskonflikten führt.

// Header.h

enum Fahrzeug
{
    Auto,
    Bus,
    Fahrrad,
    Autorikscha
};

enum Vierrad
{
    Auto,        // Fehler C2365: 'Auto': Neudefinition; vorherige Definition war 'Element'
    Kleinbus
};

enum class Editor
{
    vim,
    eclipes,
    VisualStudio
};

enum class CppEditor
{
    eclipes,       // Kein Fehler bei Neudefinitionen
    VisualStudio,  // Kein Fehler bei Neudefinitionen
    QtCreator
};

Der zugrunde liegende Typ eines Aufzählungstyps kann nicht spezifiziert werden, was zu Verwirrung, Kompatibilitätsproblemen und der Unmöglichkeit der Vorwärtsdeklaration führt.

// Header1.h
#include 

using namespace std;

enum class Port : unsigned char; // Vorwärtsdeklaration

class MyClass
{
public:
    void PrintPort(enum class Port p);
};

void MyClass::PrintPort(enum class Port p)
{
    cout << (int)p << endl;
}

.

// Header.h
enum class Port : unsigned char // Deklarieren Sie den Aufzählungstypen explizit
{
    PORT_1 = 0x01,
    PORT_2 = 0x02,
    PORT_3 = 0x04
};

.

// Source.cpp
#include "Header1.h"
#include "Header.h"

using namespace std;
int main()
{
    MyClass m;
    m.PrintPort(Port::PORT_1);

    return 0;
}

11voto

Qinsheng Zhang Punkte 856
  1. nicht implizit in int konvertieren
  2. kann wählen, welcher Typ zugrunde liegt
  3. ENUM-Namespace, um Verschmutzung zu vermeiden
  4. Im Vergleich zu normalen Klassen kann vorwärts deklariert werden, haben jedoch keine Methoden

5voto

Miro Kropacek Punkte 2592

Eine Sache, die nicht explizit erwähnt wurde - das Scope-Feature gibt Ihnen die Möglichkeit, für eine Enum und eine Klassenmethode denselben Namen zu haben. Zum Beispiel:

class Test
{
public:
   // Diese rufen intern ProcessCommand() auf
   void TakeSnapshot();
   void RestoreSnapshot();
private:
   enum class Command // wäre ohne 'class' nicht möglich
   {
        TakeSnapshot,
        RestoreSnapshot
   };
   void ProcessCommand(Command cmd); // Signalisieren Sie den anderen Thread oder was auch immer
};

3voto

Arnaud Punkte 536

Weil, wie in anderen Antworten gesagt, Klassenummern nicht implizit in int/bool konvertierbar sind, hilft es auch, fehlerhaften Code wie:

enum MyEnum {
  Value1,
  Value2,
};
...
if (var == Value1 || Value2) // Sollte "var == Value2" sein, kein Fehler/keine Warnung

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X