Zusätzlich zu Klassen unterstützt C++ Aufzählungen. Der moderne C++-Standard unterstützt sowohl Enums ohne Bereich, die in früheren Versionen von C++ eingeführt wurden, als auch C.
enum ColorTypes { Green, Yellow, Red };
Dasselbe gilt für bereichsbezogene Aufzählungen.
enum class ColorTypes { Green, Yellow, Red };
Unterscheiden von bereichsbezogenen Aufzählungen von nicht bereichsbezogenen Aufzählungen
Eine Enum mit Bereich unterscheidet sich von einer Enum ohne Bereich dadurch, dass Enum-Variablen mit Bereich nicht implizit in und aus Integer-Variablen konvertiert werden können. Für eine solche Konvertierung sollten Sie
static_cast verwenden
enum class ColorTypes { Green, Yellow, Red }; ColorTypes currentType_1 = ColorTypes::Green; // Ok ColorTypes currentType_2 = 2; // Error, преобразование невозможно int currentType_3 = ColorTypes::Red; // Error, преобразование невозможно int currentType_4 = Red; // Error, Red не существует в данной области видимости int currentType_5 = static_cast<int>(ColorTypes::Green);
Mit diesem Bereichssteuerelement können Sie Aufzählungen in einer Klasse deklarieren, deren Mitglieder den gleichen Namen haben. Es bietet auch mehr Kontrolle über den Code, obwohl es eine Reihe von Einschränkungen auferlegt.
Wie Enum-Werte gesetzt werden
Standardmäßig beginnt eine Aufzählung bei 0, und dann werden die Aufzählungsmitglieder inkrementiert ...
enum class ColorTypes { Green, // 0 Yellow, // 1 Red, // 2 Black, // 3 Blue // 4 };
Es ist jedoch möglich, beim Deklarieren eigene Werte für Aufzählungen festzulegen.
enum class ColorTypes { Green = 15, // 15 Yellow, // 16 Red = 24, // 24 Black = ColorTypes::Red, // 24 Blue // 25 };
Switch Cases für Aufzählungen verwenden
Sowohl bereichsbezogene als auch bereichslose Aufzählungen unterstützen switch/case -Bedingungs- und Verzweigungsoperatoren:
ColorTypes currentType = ColorTypes::Green; switch (currentType) { case ColorTypes::Green: std::cout << "Green"; break; case ColorTypes::Yellow: std::cout << "Yellow"; break; case ColorTypes::Black: std::cout << "Black"; break; case ColorTypes::Blue: std::cout << "Blue"; break; default: std::cout << "Unknown Type"; break; }
Wenn wir über Code-Ausführungskontrolle und die auferlegten Einschränkungen bei der Verwendung von Enumerationen mit und ohne Gültigkeitsbereich sprechen, dann können wir aus irgendeinem Grund eine Situation simulieren, wenn wir uns in switch / case befinden (Tippfehler, Copy-Paste, Noob, sie haben es vermasselt, wenn Konflikte gelöst wurden, wenn Verzweigungen zusammenführen) gibt es Aufzählungen verschiedener Typen. Dann werden Aufzählungen ohne Gültigkeitsbereich vom Compiler implizit in den erforderlichen Typ konvertiert und der Code wird ausgeführt, obwohl er fehlerhaft ist, und im Fall von Aufzählungen mit Gültigkeitsbereich wird der Compiler einen Fehler melden und das Erstellen des Programms abbrechen .
Das heißt, der folgende Code, der fehlerhaft ist, wird kompiliert:
enum SideTypes { Top, Bottom, Right, Left }; enum ColorTypes { Green = 8, Yellow, Red, Blue }; int main(int argc, char *argv[]) { ColorTypes currentType = ColorTypes::Green; switch (currentType) { case SideTypes::Top: std::cout << "Top Side"; break; case ColorTypes::Green: std::cout << "Green"; break; case ColorTypes::Yellow: std::cout << "Yellow"; break; case ColorTypes::Red: std::cout << "Red"; break; case ColorTypes::Blue: std::cout << "Blue"; break; default: std::cout << "Unknown Type"; break; } return 0; }
Im besten Fall wirft der Compiler eine Warnung aus.
warning: case value ‘0’ not in enumerated type ‘ColorTypes’ [-Wswitch] case SideTypes::Top: std::cout << "Top Side"; break; ^
Aber es kommt vor, dass der Programmierer "C++ besser kennt und versteht als der Compiler" und Warnungen deaktiviert.
Während der folgende Code einfach nicht kompiliert wird:
enum class SideTypes { Top, Bottom, Right, Left }; enum class ColorTypes { Green = 8, Yellow, Red, Blue }; int main(int argc, char *argv[]) { ColorTypes currentType = ColorTypes::Green; switch (currentType) { case SideTypes::Top: std::cout << "Top Side"; break; case ColorTypes::Green: std::cout << "Green"; break; case ColorTypes::Yellow: std::cout << "Yellow"; break; case ColorTypes::Red: std::cout << "Red"; break; case ColorTypes::Blue: std::cout << "Blue"; break; default: std::cout << "Unknown Type"; break; } return 0; }
Der Compiler gibt einen Kompilierungsfehler aus:
error: could not convert ‘Top’ from ‘SideTypes’ to ‘ColorTypes’ case SideTypes::Top: std::cout << "Top Side"; break; ^
So legen Sie einen bestimmten Integer-Typ für eine Aufzählung fest
Enums können auch einen spezifischeren Typ haben, der ein definierter ganzzahliger Typ sein muss:
- Zeichen ohne Vorzeichen;
- Zeichen;
- Ganzzahl;
- lange Ganzzahl;
- usw.
Auf diese Weise können Sie Variablen mit Enum-Werten eine bestimmte Menge an Speicher zuweisen. Vielleicht ist dies für die eingebettete Entwicklung relevant. Je nach Zielplattform wird eine bestimmte Menge an Speicher zugewiesen.
enum class SideTypes : short int { Top, Bottom, Right, Left };
Iterator zum Aufzählen
Und schließlich erstellen wir einen Iterator für Aufzählungen, mit dem Sie die bereichsbasierte for -Schleife verwenden können.
#include <iostream> enum class ColorTypes { Blue, Red, Green, Purple, First=ColorTypes::Blue, // участник перечисления для первого элемента Last=ColorTypes::Purple // участник перечисления для последнего элемента }; ColorTypes operator++(ColorTypes& x) { // std::underlying_type преобразовывает тип ColorTypes в целочисленный тип, под которым данный enum был объявлен return x = static_cast<ColorTypes>(std::underlying_type<ColorTypes>::type(x) + 1); } ColorTypes operator*(ColorTypes c) { return c; } ColorTypes begin(ColorTypes r) { return ColorTypes::First; } ColorTypes end(ColorTypes r) { ColorTypes l=ColorTypes::Last; return ++l; } int main(int argc, char *argv[]) { // Используем круглые скобки для инстанцирования перечисления for(const auto& c : ColorTypes()) { std::cout << static_cast<int>(c) << std::endl; } return 0; }
классная статья! Большое спасибо. Хотел бы добавить для тех, кто будет использовать это в другом классе- перед операторами и методами begin(), end() нужно поставить friend.