was bringt enum, wozu?



  • hi folks!

    mal ne DAU-style frage: was genau macht ENUM in C und C++?
    wenn ich es richtig verstehe wird jeder enumerierten variable ein wert zugeteilt, der 1 höher als bei der vorgehenden ist.
    hoffe das stimmt schonmal.

    aber: wozu braucht man das? also richtig, für welche aufgaben etc. kann mir nix vorstellen.

    nicht böse werden, ehrlich, kann mir wirklich nix vorstellen!

    🙂

    ---loki



  • enum MESSAGE_TYPE
    {
        MT_OPEN,
        MT_CLOSE,
        MT_HUGO123
    };
    
    void handleMessage (MESSAGE_TYPE type, int param)
    {
        switch(type)
        {
            case MT_OPEN:
                foo_open(param);
            break;
        }
    }
    

    1. Schöner und übersichtlicherer Code als hier irgendwelche Nummerkonstanten zu übergeben
    2. Spart man sich dumme Range-Abfragen wenn der User nicht auf stranges Casting kommt
    3. Weiß ich nicht, kommt aber bestimmt noch jemand dahinter.

    MfG SideWinder



  • Damit erzeugt man symbolische Konstanten oder nimmst du etwas immer #define oder int const?



  • Der Vorteil ist ganz einfach, das die übergebenen Werte typsicher sind. Bsp.:

    void foo(int wochentag);
    

    Bei dem Bsp. ist das Problem, das dir jeder jeden beliebigen Wert übergeben kann. Klar könntest du dann innerhalb foo eine Range-Abfrage machen, aber das ist doch nervig: unnötiger Programmieraufwand -> möglicher Fehler. Und der Benutzer von foo muß auch schauen, was er überhaupt übergeben kann.

    Wenn du aber eine Wochentags-Enumeration hast:

    enum Wochentage { Montag, // 0
    Dienstag, // 1
    Mittwoch, // 2
    Donnerstag,  // 3
    Freitag,  // 4
    Samsatg,  // 5
    Sonntag}; // 6
    
    void foo(Wochentage wochentag);
    

    Dann kann man dir garantiert nur Wochentage übergeben, du kannst dir die Rangeabfrage sparen. Und der Benutzer von foo hast einfacher.

    Was noch? Achja! Sowas:

    // Upps, Wochentage müssen geändert werden!
    enum Wochentage { Montag, // 0
    Dienstag,  // 1
    Mittwoch = 100, // 100
    Donnerstag,  // 101
    Freitag,  // 102
    Samsatg,  // 103
    Sonntag}; // 104
    
    void foo(Wochentage wochentag);
    

    Wenn man Konstanten definiert hätte, hätte man ALLE Werte ab Mittwoch ändern müssen. Also bei Donnerstag hätte man 101 setzen müssen, obwohl es vorher 4 war. Denn Enum zählt autom. hoch. Und man kann ganz leicht mitten drin die Zählung ändern.

    Klar, bei 7 Tagen ist das einfach mit Konstanten zu ändern. Aber was ist wenn man 100 Enums drin hätte? Alle nachfolgenden mit ändern? Weiterhin müsstest du auch die Range-Abfrage anpassen. 😡

    Eigentlich geht es doch bei Hochsprachen doch nur darum, die Arbeit zu erleichtern und die Fehlerquote zu senken. Und genau solche Dinge macht enum. Klar kommt beim compilieren nur ein Zahlenwert am Ende raus, aber darum geht es ja nicht.



  • ...it blows off your whole foot:

    static_cast<Wochentag>(1337);
    

    MfG SideWinder



  • SideWinder schrieb:

    ...it blows off your whole foot:

    static_cast<Wochentag>(1337);
    

    Vorsätzlich kann man so ziemlich alles kaputt machen...



  • Das muss nichts mit Vorsatz zu tun haben, es kann durchaus Gelegenheiten geben, wo man so einen Cast braucht und es ist schade, dass er nicht checked ist. Gibt aber glaub ich irgendein boost-Teil als Ersatz für enums, was AFAIK auch noch den Vorteil hat, dass man den enum-Typ definieren kann. Das ist nämlich etwas, was wirklich sinnvoll ist, es gibt keinen Grund, warum ein enum immer ein integraler Typ sein soll.

    Coole Sache:

    enum Weekday {
    	Monday(false), Tuesday(false), Wednesday(false), Thursday(false),
    	Friday(false), Saturday(true), Sunday(true);
    
    	private Weekday(boolean free) {
    		this.free = free;
    	}
    
    	public boolean isFree()		{ return free; }
    
    	private boolean free;
    }
    
    ...
    
    Weekday foo = ...;
    System.out.println("Freier Tag? " + foo.isFree());
    


  • OK, vielen dank. jetzt hab ich den durchblick...

    denke das ist ab und an durchaus nützlich!

    danke 🙂



  • Optimizer schrieb:

    Das muss nichts mit Vorsatz zu tun haben, es kann durchaus Gelegenheiten geben, wo man so einen Cast braucht ...

    Hast du grad ein Beispiel zur Hand?



  • Man könnte beispielsweise den Wochentag haben wollen, der auf den aktuellen folgt.

    Weekday day = ...;
    day = (Weekday)(((int)day) + 1);
    

    In C++ geht so eine Umwandlung zwar implizit, das ändert aber nichts daran, dass irgendwas ausgerechnet wird und das Ding wieder in ein enum "gecastet" wird. (Ein enum ist natürlich nur eine Einbildung von irgendwas, intern ist es in beiden Sprachen nichts anderes als ein integraler Typ.) Tatsache ist, dass es beim Sonntag Probleme gibt und das ist dann nicht mutwillig, sondern nur leichtsinnig.

    Oder man könnte den Zustand von irgendwas in eine Datei speichern, da würde ich auch einfach die x Bytes reinschreiben und beim laden wieder casten und mir nicht aufwändig eine andere Repräsentation für das enum überlegen.



  • Optimizer schrieb:

    Man könnte beispielsweise den Wochentag haben wollen, der auf den aktuellen folgt.

    Weekday day = ...;
    day = (Weekday)(((int)day) + 1);
    

    In C++ geht so eine Umwandlung zwar implizit, das ändert aber nichts daran, dass irgendwas ausgerechnet wird und das Ding wieder in ein enum "gecastet" wird. (Ein enum ist natürlich nur eine Einbildung von irgendwas, intern ist es in beiden Sprachen nichts anderes als ein integraler Typ.) Tatsache ist, dass es beim Sonntag Probleme gibt und das ist dann nicht mutwillig, sondern nur leichtsinnig.

    Hmm. Dass es beim Sonntag Probleme gibt ist nicht wirklich ein enum-Problem sondern liegt eher daran dass die Logik schlicht falsch ist.

    Wochentag operator+( Wochentag lhs, int rhs )
    {
      const int N = 7;
      return static_cast<Wochentag>((static_cast<int>(lhs)+rhs)%N);
    }
    
    std::ostream& operator<<( std::ostream& out, Wochentag w )
    {
      switch (w) {
      case Montag:     out << "Montag"; break;
      case Dienstag:   out << "Dienstag"; break;
      case Mittwoch:   out << "Mittwoch"; break;
      case Donnerstag: out << "Donnerstag"; break;
      case Freitag:    out << "Freitag"; break;
      case Samstag:    out << "Samstag"; break;
      case Sonntag:    out << "Sonntag"; break;
      };
      return out;
    }
    
    int main()
    {
      Wochentag w = Montag;
      for (int i = 0; i < 21; ++i) {
        cout << w+i << '\n';
      }
      cout.flush();
    }
    

    Sieht schon etwas geschickter aus, oder? So könntest wären selbst Änderungen wie in Artchis Post nicht allzu aufwändig.

    Optimizer schrieb:

    Oder man könnte den Zustand von irgendwas in eine Datei speichern, da würde ich auch einfach die x Bytes reinschreiben und beim laden wieder casten und mir nicht aufwändig eine andere Repräsentation für das enum überlegen.

    Und?

    Ich behaupte ja gar nicht dass das C++-enum wirklich toll ist, nur das viele Probleme wie z.B. Sides Cast oder dein Sonntagsdilemma nicht am enum liegen sondern weil die Programmlogik schlicht WTF ist.


Anmelden zum Antworten