C++ Kurs

enum Datentyp

Die Themen:

Syntax
Beispiel 1
Werte der enum-Konstanten
Fehlerfallen
Beispiel 2

Syntax

Der enumerated Datentypen (im Folgenden einfach enum genannt) wird immer dann verwendet, wenn eine Menge logisch zusammengehöriger Konstanten definiert werden soll. Der enum Datentyp wird oft auch als Aufzählungsdatentyp bezeichnet.

Die enum Anweisung hat die nachfolgend angegebene Syntax.

enum [Name] { KONST1[=VAL1],KONST2[=VAL2],... } [enumVar1,...];

Nach dem Schlüsselwort enum folgt (optional) ein Name, der den enum-Datentyp eindeutig kennzeichnet. Durch Angabe dieses Namens (und optionalem Schlüsselwort enum vor dem Namen) können Sie dann zu einem beliebigen Zeitpunkt entsprechende enum-Variablen oder auch Funktionsparameter mit diesem enum-Datentyp definieren.

Innerhalb der geschweiften Klammern folgen dann die Bezeichner (Konstanten), die mit dem enum-Datentyp verbunden sein sollen. Welche 'numerischen Werte' diese Bezeichner letztendlich besitzen, das erfahren Sie gleich noch.

Nach der schließenden geschweiften Klammer können optional noch Variablen des entsprechenden enum-Datentyps definiert werden.


// enum-Datentyp definieren und gleichzeitig
// eine enum-Variable definieren

enum Colors
{
   RED, YELLOW, GREEN, BLUE
} myColors;
// weitere enum-Variablen definieren
Colors color1, color2;

Im Beispiel wird der enum-Datentyp Colors definiert und dabei auch gleichzeitig die enum-Variable myColors. Im Anschluss daran werden zwei weitere Variablen color1 und color2 dieses enum-Datentyps angelegt.

Einer enum-Variable kann dann im Verlaufe des Programms nur eine der innerhalb des enum-Blocks definierten Bezeichner zugewiesen werden.

Beispiel 1

Sehen wir uns die Wirkungsweise des enum-Datentyps anhand eines kleinen Beispiels an. Ziel der nachfolgenden Anweisungen ist es, die für eine Schaltfläche (Button) möglichen Zustände durch benannte Konstanten festzulegen. Eine Schaltfläche soll z.B. folgende 3 Zustände annehmen können: gesperrt, ausgewählt und gedrückt. Für jeden dieser Zustände werden entsprechende benannte Konstanten definiert. Die Schaltfläche selbst wird durch eine int-Variable repräsentiert, der dann je nach Zustand eine der definierten Konstanten zugewiesen wird.


// Definition der Schaltflächen-Konstanten
const int DISABLED = 0;
const int FOCUS = 1;
const int PRESSED = 2;
// Definition der Schaltflächen-Variablen
int button;
...
// Zuweisen eines Zustands
button = DISABLED;

Mithilfe einer enum-Anweisung kann nun die Definition der Konstanten und die Definition der Variable in einer einzigen Anweisung zusammengefasst werden. Dazu werden innerhalb des Blocks der enum-Anweisung einfach die Konstanten aufgelistet. Diese Konstanten werden automatisch fortlaufend durchnummeriert, wobei die erste Konstante den Wert 0 besitzt, die zweite den Wert 1 usw.


// enum Definition
enum Button {DISABLED, FOCUS, PRESSED} button1;
// Definition einer weiteren Schaltfläche
Button button2;

int main()
{
   int var;
   ...
   button2 = FOCUS;
   // enum-Konstante einem int zuweisen
   var = DISABLED;
   ...

Die in einer enum-Anweisung definierten Bezeichner (Konstanten) können im Programm ebenfalls wie 'normale' benannte Konstanten verwendet werden (siehe letzte Anweisung oben im Beispiel). Daraus folgt, dass alle in einem Programm definierten enum-Konstanten unterschiedliche Namen besitzen müssen. Ausnahme: enum-Konstanten die innerhalb von Klassen definiert werden, aber dazu später mehr.

Werte der enum-Konstanten

Einer enum-Konstante kann innerhalb des enum-Blocks explizit ein bestimmter Wert zugeordnet werden. Hierzu wird nach dem Konstantennamen der Zuweisungsoperator angegeben, gefolgt von dem gewünschten Wert.


// Definition
enum Button {DISABLED=1, FOCUS, PRESSED=FOCUS+10} button1;

Alle nach einer solchen Zuweisung folgenden Konstanten werden dann, wenn sie keinen erneuten expliziten Wert erhalten, wieder fortlaufend jeweils um eins erhöht. Für enum-Konstanten sind übrigens nur Ganzzahlwerte zugelassen. Zusatzlich ist es erlaubt, eine bereits in der Liste definierte Konstante zur Berechnung des Wertes einer weiteren Konstanten zu verwenden. Im Beispiel besitzt die Konstante DISABLED den Wert 1, FOCUS den Wert2  und PRESSED den Wert 12.

Und wie jede andere Variable kann auch eine enum-Variable bei ihrer Definition gleich initialisiert werden, jedoch nur meiner ihrem Datentyp zugehörigen Konstante.

Fehlerfallen

Zum Schluss dieser kleinen Lektion noch zwei Hinweise:

  1. Einer enum-Variable nicht ohne weiteres einen int-Wert zuweisen, selbst wenn dieser int-Wert durch eine entsprechende Konstante definiert ist.
  2. Eine enum-Variablen kann zwar innerhalb einer Schleifen verwendet werden, jedoch können Sie mit dieser Variable keine Rechenoperationen durchführen, d.h. die nachfolgend in der zweiten for-Schleife angegebene Anweisung button1++ führt zu einem Fehler.

// Definition
enum Button{DISABLED=1, FOCUS, PRESSED=FOCUS+10} button1;

// Keine int-Zuweisung erlaubt
button1 = 1;

// enum in einer for-Schleife
for (button1=FOCUS; button1!=DISABLED;)
   ...
// Aber das geht nicht!
for (button1=FOCUS; button1!=DISABLED; button1++)
   ...

Eine weitere Fehlerfalle lauert bei der Übergabe von enum-Parameter an Funktionen. Im Beispiel unten wird der enum-Datentyp Style z.B. zur Aufnahme von verschiedenen Zeichenstilen definiert. Die Funktion Func(...) soll jetzt als Parameter einen Wert dieses enum-Typs erhalten. Damit sieht die Deklaration der Funktion Func(...) wie unten angegeben aus. Wird diese Funktion nun mit einem einzigen enum-Wert aufgerufen, so ist alles in Ordnung (erster Funktionsaufruf). Doch Vorsicht! Werden mehrere enum-Werte beim Aufruf der Funktion z.B. verodert, so meldet der Compiler beim Übersetzen einen Fehler (zweiter Funktionsaufruf). Der Grund hierfür liegt darin, dass die Veroderung von zwei Werten einen Integral-Datentyp zurückliefert (hier int). Und damit passt der Aufruf nicht mehr zur Funktionsdeklaration. Sie müssen dann das Ergebnis der Veroderung explizit wieder in den entsprechenden enum-Datentyp konvertieren (letzter Funktionsaufruf).


// Enum-Definition
enum Style {STYLE1, STYLE2, STYLE3};

// Funktionsdeklaration
void Func(Style newStyle);

// So geht's
Func(STYLE2);
// Das geht schief
Func(STYLE1|STYLE2);
// So geht's wieder
Func(static_cast<Style>(STYLE1|STYLE2));

Beispiel 2

Das Beispiel simuliert den Schaltzyklus einer Verkehrsampel. Die einzelnen Ampelphasen werden hierbei durch entsprechende enum-Konstanten definiert.

In der main() Funktion werden in einer while-Schleife die Ampelphase durchlaufen. Beachten Sie bitte, dass die Ampelphasen explizit der enum-Variable zugewiesen werden müssen, da keine Rechenoperationen mit enum-Variablen erlaubt sind.


// Beispiel zum enum Datentyp

// Dateien einbinden

#include <iostream>

using std::cout;
using std::endl;

// main() Funktion
int main()
{
   // enum-Variable definieren und initialisieren
   enum eAMPEL {eROT1, eROTGELB, eGRUEN, eGELB, eROT2};
   eAMPEL eAmpel=eROT1;

   // Alle Ampelphasen durchlaufen
   do
   {
      // Aktuelle Ampelphase auswerten, den entsprechenden Text
      // ausgeben und nächste Ampelphase aufschalten

      switch (eAmpel)
      {
      case eROT1:
      case eROT2:
         cout << "Die Ampel hat rot!\n";
         if (eAmpel == eROT1)
            eAmpel = eROTGELB;
         else
            eAmpel = eROT1;
         break;
      case eROTGELB:
         cout << "Die Ampel hat rot-gelb\n";
         eAmpel = eGRUEN;
         break;
      case eGRUEN:
         cout << "Die Ampel hat grün\n";
         eAmpel = eGELB;
         break;
      case eGELB:
         cout << "Die Ampel hat gelb\n";
         eAmpel = eROT2;
         break;
      }
   } while (eAmpel != eROT1);
}

Die Ampel hat rot!
Die Ampel hat rot-gelb
Die Ampel hat grün
Die Ampel hat gelb
Die Ampel hat rot!

So, die nächste Lektion befasst sich mit Bitfeldern und ist hauptsächlich etwas für die hardwarenahe Programmierung. Wenn Sie wollen, können Sie diese Lektion überspringen, da Bitfelder im weiteren Verlaufe des Kurses nicht mehr benötigt werden. Wenn Sie die Lektion überspringen wollen, klicken Sie hier um mit den Präprozessor-Direktiven fortzufahren.