C++-Programmierung: Aufzählungen
Eine aktuelle Seite zum gleichen Thema ist unter C++-Programmierung/ Weitere Grundelemente/ Aufzählungen verfügbar.
Eine Aufzählung (enumeration) bietet die Möglichkeit, mehrere (i.d.R. „semantisch zusammengehörige“) Konstanten zu einer Menge zusammenzufassen. Die enum
-Deklaration legt den Namen der Aufzählung und die Namen der einzelnen Konstanten fest.
enum Wochentage
{
Montag,
Dienstag,
Mittwoch,
Donnerstag,
Freitag,
Samstag,
Sonntag
};
Die Namen
Montag ... Sonntag
können dann wie normale Konstanten verwendet werden. Eine Variable, die nur Wochentage aufnimmt, kann durch
Wochentage tag;
deklariert werden. Die Wertzuweisung erfolgt z.B. so:
tag = Montag;
Gemäß dem C++-Standard stellt jede Aufzählung einen eigenständigen ganzzahligen Typ dar. Eine Zuweisung der Art
tag = 7;
ist daher illegal. Sie wird aber von vielen Compilern akzeptiert oder lediglich mit einer Warnung beantwortet. Will man diese Zuweisung jedoch tatsächlich, hilft hier eine explizite Typumwandlung:
tag = Wochentage(7);
Diese Zuweisung ist völlig legal (wenngleich nicht sonderlich sinnvoll). Allerdings muß man aufpassen: Die Zuweisung
tag = Wochentage(1000);
ergibt zwar keine Warnung und funktioniert auch auf vielen Compilern, das ist jedoch nicht garantiert! Beispielsweise könnte der Compiler den Aufzählungstyp in nur einem Byte speichern, und dafür ist 1000 einfach zu groß. In der Tat ist der Erfolg der Zuweisung nur garantiert, solange der zugewiesene Wert nicht mehr Bits benötigt als die deklarierten Bezeichner. Im Beispiel erhalten die Wochentage bei der die numerischen Werte 0 bis 6; da diese Werte alle mit 3 Bits dargestellt werden können, dürfen auch bei expliziten Typumwandlungen nur solche Werte verwendet werden, die ebenfalls mit 3 Bits dargestellt werden können, also die Werte 0 bis 7. Auch wenn ein Aufzählungstyp immer mindestens ein Byte belegt, und daher Werte bis 255 sicher erscheinen, ist es gefährlich, sich darauf zu verlassen: Moderne Optimierer benutzen zum Teil derartige Einschränkungen, um effizienteren Code produzieren zu können, der jedoch nicht wie erwartet funktionieren muss, wenn man die Regeln missachtet.
Die umgekehrte Zuweisung
int a = Mittwoch;
ist korrekt. Sofern die enum-Deklaration keine konkreten Werte spezifiziert, werden die Konstanten 0, 1, ... gezählt und bei Bedarf in entsprechende int
-Werte umgewandelt (integral promotion). Im Beispiel würde also a = 2
zugewiesen.
Da Aufzählungstypen benutzerdefinierte Typen sind, lassen sich für sie auch Operatoren definieren. So könnte man z.B. den Inkrement-Operator definieren, um zum nächsten Tag zu gelangen:
// Prä-Inkrement
Wochentage& operator++(Wochentage& w)
{
return w = Wochentage((w+1)%7);
}
// Post-Inkrement
Wochentage operator++(Wochentage& w, int)
{
Wochentage alt = w;
++w;
return alt;
}
Der Prä-Inkrement-Operator benutzt hierbei die automatische Umwandlung in einen Integer-Typ, um den Tag um 1 (modulo 7) zu erhöhen. Der Rückweg benötigt dann eine explizite Umwandlung.