Enumerator-Deklaration, -Definition und -Verwendung

Wie wir alle wissen, kann die Sprache C/C++#defineundconstverwenden, um symbolische Konstanten zu erstellen, und die Verwendung vonenumDas Tool kann nicht nur symbolische Konstanten erstellen, sondern auch neue Datentypen definieren, aber es muss nach bestimmten Regeln erfolgen. Schauen wir unsenumund seine Verwendung an.

Schritt (1) — Deklaration und Definition von Enumeratoren

(1) Betrachten Sie zunächst die folgende Anweisung:

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

Diese Anweisung hat zwei Funktionen:

  • Erstens: Sie deklariert enumType als neuen Datentyp, der als Enumeration bezeichnet wird;
  • Zweitens: Sie deklariert Monday, Tuesday usw. als symbolische Konstanten, gewöhnlich Enumeratoren genannt, deren Standardwerte jeweils 0-6 sind. (Wir werden später vorstellen, wie man Enumeratorwerte explizit initialisiert.)

(2)Verwenden Sie dann den neuen Aufzählungstyp enumType, um Variablen dieses Typs zu deklarieren: enumType Weekday, genau wie beim Deklarieren einer Variablen mit dem grundlegenden Variablentyp int, z. B. int a; Sie können auch Aufzählungsvariablen beim Definieren des Aufzählungstyps definieren.

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}Weekday;

Im Gegensatz zu grundlegenden Variablentypen können Sie jedoch ohne eine Typumwandlung (Cast) nur die definierten Enumeratoren einer Variablen dieses Aufzählungstyps zuweisen. Zum Beispiel: Weekday = Monday; oder Weekday = Sunday; Sie können einer Aufzählungsvariablen keine anderen Werte zuweisen, z. B. Weekday = 10; Dies ist nicht erlaubt, weil 10 kein Enumerator ist. Mit anderen Worten: Weekday kann nur die definierten Enumeratoren Monday–Sunday annehmen. Aber das ist nicht absolut; der sechste Punkt wird die Verwendung einer Typumwandlung (Cast) behandeln, um Werte anderer Typen Aufzählungsvariablen zuzuweisen.

(3)Oben wurde gesagt, dass Nicht-Enumerator-Werte nicht Aufzählungsvariablen zugewiesen werden können. Können dann Enumeratoren Nicht-Aufzählungsvariablen zugewiesen werden? Zum Beispiel:int a=Monday;Dies ist erlaubt, weil Enumeratoren symbolische Konstanten sind. Bei dieser Zuweisung konvertiert der Compiler den Enumerator automatisch in den Typ int.

(4)Früher haben wir gesagt, dass Zuweisungsoperationen auf Aufzählungen ausgeführt werden können. Können mit Aufzählungsvariablen arithmetische Operationen durchgeführt werden?

Weekday++;Weekday = Monday + Tuesday;

Dies ist unzulässig, weil diese Operationen zu Verletzungen der Typbeschränkungen führen können. Zum Beispiel:

Weekday = Sunday;
Weekday++;

Weekday wird zuerst der letzte Enumeratorwert Sunday (Wert 6) zugewiesen. Wenn weiter inkrementiert wird, würde Weekday auf 7 erhöht, aber 7 ist für den Typ enumType ungültig.

Zusammenfassung:Für Aufzählungen ist nur der Zuweisungsoperator definiert; arithmetische Operationen sind für Aufzählungen nicht definiert.

(5)Arithmetische Operationen können nicht mit Enumeratoren durchgeführt werden. Können Enumeratoren dann an Operationen mit Variablen anderer Typen teilnehmen?

int a;
a = 1 + Monday;

Dies ist erlaubt, weil der Compiler Enumeratoren automatisch in den Typ int konvertiert.

(6)Der zweite Punkt besagte: Ohne einen Cast können nur die definierten Enumeratoren einer Variablen dieses Enumerationstyps zugewiesen werden. Das impliziert, dass Werte anderer Typen durch einen Cast Enumerationsvariablen zugewiesen werden können:

Weekday = enumType(2);

Entspricht:

Weekday = Wednesday;
Aber was würde passieren, wenn man versucht, einer Enumerationsvariablen durch einen Cast einen Wert außerhalb des Wertebereichs der Enumeration zuzuweisen?
Weekday = enumType(20);

Das Ergebnis ist undefiniert. Dies führt nicht zu einem Fehler, aber man erhält nicht das gewünschte Ergebnis.

Schritt (2) — Anpassen der Enumeratorwerte

(1)Zuvor haben wir darüber gesprochen, zu definierenenum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};Die Enumeratoren Monday, Tuesday usw. haben standardmäßig die Werte 0-6. Wir können die Werte der Enumeratoren explizit festlegen:

enum enumType {Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7};

Die angegebenen Werte müssen ganze Zahlen sein!

(2)Man kann auch nur einige der Enumeratorwerte explizit definieren:

enum enumType {Monday=1, Tuesday, Wednesday=1, Thursday, Friday, Saturday, Sunday};

Auf diese Weise werden sowohl Monday als auch Wednesday als 1 definiert, also ist Tuesday=2, und die Standardwerte von Thursday, Friday, Saturday und Sunday sind 2, 3, 4 bzw. 5.

Zusammenfassung:Der Wert eines nicht initialisierten Enumerators ist standardmäßig um 1 größer als der Wert des vorhergehenden Enumerators.

(3)Der zweite Punkt veranschaulicht außerdem ein weiteres Phänomen: Enumeratorwerte können gleich sein.

Schritt (3) — Der Wertebereich einer Enumeration

Zuvor wurde erwähnt, dass Werte anderer Typen durch einen Cast Enumerationsvariablen zugewiesen werden können:

Weekday = enumType(2);

Dies ist zulässig;

Aber

Weekday = enumType(20);

ist unzulässig. Dies betrifft das Konzept des Wertebereichs einer Enumeration: Die Obergrenze einer Enumeration ist die kleinste Zweierpotenz, die größer als der maximale Enumerator ist, minus 1;

Die Untergrenze einer Enumeration hat zwei Fälle: 1. Wenn der minimale Enumeratorwert nicht kleiner als 0 ist, ist die Untergrenze 0; 2. Wenn der minimale Enumeratorwert kleiner als 0 ist, ist die Untergrenze die größte Zweierpotenz, die kleiner als der minimale Enumerator ist, plus 1.

Zum Beispiel:

Angenommen, wir definierenenum enumType1 { First=-5,Second=14,Third=10 };Dann ist die Obergrenze der Enumeration 16-1=15 (16 ist größer als der maximale Enumerator 14 und ist eine Zweierpotenz); die Untergrenze ist -8+1=-7 (-8 ist kleiner als der minimale Enumerator -5 und ist eine Zweierpotenz).

Schritt (4) — Enumeration-Anwendungen

Ich persönlich denke, enum und switch sind die besten Partner:

enum enumType{Step0, Step1, Step2}Step=Step0; // 注意这里在声明枚举的时候直接定义了枚举变量 Step,并初始化为 Step0

switch (Step)x
{
  case Step0:{...;break;}
  case Step1:{...;break;}
  case Step2:{...;break;}
  default:break;
}

Außerdem gibt es eine seltene Verwendung von enum, nämlichenum { one ,two ,three};das heißt, keinen Namen anzugeben. Auf diese Weise können wir natürlich keine Enumerationstypen definieren. An diesem Punkt ist es äquivalent zustatic const int one = 0;drei Konstanten wie folgt zu definieren. Wenn man es dann verwendet, schreibt man einfachint no = one。


Stark typisierte Enums

1. Kurze Beschreibung

Stark typisierte Enums, auch bekannt als enum classes, sind eine neue Syntax in C++11, die verwendet wird, um die Mängel traditioneller C++-Enumerationstypen zu beheben. In traditionellem C++ werden Enumerationskonstanten dem äußeren Gültigkeitsbereich ausgesetzt, sodass zwei verschiedene Enumerationstypen im selben Gültigkeitsbereich nicht dieselbe Enumerationskonstante enthalten können. Zum Beispiel:

enum Side{Right,Left};
enum Thing{Wrong,Right};

Sie können nicht zusammen verwendet werden.

Ein weiterer Defekt besteht darin, dass traditionelle Enumerationswerte immer implizit in Ganzzahlen umgewandelt werden und Benutzer den zugrunde liegenden Typ nicht definieren können. Stark typisierte Enums in C++11 lösen diese Probleme.

2. Stark typisierte Enums

Stark typisierte Enums verwenden die Syntax `enum class` zur Deklaration, wie folgt:

enum class Enumeration{
    VAL1,
    VAL2,
    VAL3=100,
    VAL4
};

Auf diese Weise ist der Enumerationstyp sicher, und Enumeratorwerte werden weder implizit in Ganzzahlen umgewandelt, noch können sie mit Ganzzahlwerten verglichen werden. Zum Beispiel (`Enumeration::VAL4 == 10` löst einen Kompilierfehler aus).

Darüber hinaus ist der vom Enumerationstyp verwendete zugrunde liegende Typ standardmäßig `int`, aber es können auch andere Typen angegeben werden, zum Beispiel:

enum class Enum:unsigned int{VAL1,VAL2};

Wie bereits erwähnt, können stark typisierte Enums das Problem traditioneller Enums lösen, dass dieselben Enumeratornamen in verschiedenen Enumerationklassen vorkommen. Bei der Verwendung eines Enumerators eines Enumerationstyps müssen Sie seinen Gültigkeitsbereich angeben, zum Beispiel: `Enum::VAL1`, während `VAL1` allein keine Bedeutung mehr hat.

Ein weiterer erwähnenswerter Punkt ist, dass die Vorwärtsdeklaration von Enumerationstypen in C++11 ebenfalls möglich ist, zum Beispiel:

enum class Enum;
enum class Enum1:unsigned int;

3. Codeausschnitte für stark typisierte Enums in Projekten

1. Bildverarbeitung

enum class Color{RED,BLUE,YELLOR,BLACK,WHITE};

2. Ampeln

enum class TrafficLight{RED,YELLOR,GREEN};

Stark typisierte Enumeratoren haben die Funktionalität traditioneller Enums – das Benennen von Enumeratorwerten – und besitzen außerdem klassenähnliche Eigenschaften: Sie haben klassenbezogene Mitglieder und können keine Standardtypkonvertierung durchlaufen. Daher werden sie auch Enum-Klassen genannt – `enum class`.

Der zugrunde liegende Datentyp einer Enum-Klasse muss ein vorzeichenbehafteter oder vorzeichenloser Ganzzahltyp sein, wie `char`, `unsigned int`, `unsigned long`; der Standard ist `int`.

3. Anwendung der Vorwärtsdeklaration

enmu class Clolor:char;            //前置声明枚举类
void Foo(Color*p);                     //前置声明的使用
//....................
enum class Color:char{RED,GREEN,BLACK,WHITE};      //前置声明的定义

Referenz: http://blog.csdn.net/u012333003/article/details/20612267