Evgenii Legotckoi
Evgenii Legotckoi2. September 2017 07:25

C++ - Tutorial 008. Aufzählungen

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;
}
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

ДК
  • 26. November 2019 09:38
  • (bearbeitet)

классная статья! Большое спасибо. Хотел бы добавить для тех, кто будет использовать это в другом классе- перед операторами и методами begin(), end() нужно поставить friend.

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken