Zwei Aufzählungen haben einige Elemente gemeinsam, warum erzeugt dies einen Fehler?

Lesezeit: 4 Minuten

Benutzeravatar von Pieter
Peter

Ich habe zwei Enums in meinem Code:

enum Month {January, February, March, April, May, June, July,
        August, September, October, November, December};
enum ShortMonth {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};

May ist ein gemeinsames Element in beiden Aufzählungen, also sagt der Compiler:

Neudeklaration des Enumerators ‘May.

Warum sagt es das? Und wie kann ich das umgehen?

Benutzeravatar von unwind
entspannen

Aufzählungsnamen sind global gültig, sie müssen eindeutig sein. Denken Sie daran, dass Sie die Aufzählungssymbole nicht mit dem Aufzählungsnamen qualifizieren müssen, sondern nur:

Month xmas = December;

nicht:

Month xmas = Month.December;  /* This is not C. */

Aus diesem Grund sehen Sie oft Leute, die den Symbolnamen den Namen der Aufzählung voranstellen:

enum Month { Month_January, Month_February, /* and so on */ };

  • Gibt es dennoch ein Szenario, in dem die beiden Namen in Konflikt geraten könnten? Können sie beispielsweise einer Aufzählung ihres eigenen Typs zugewiesen oder mit ihr verglichen werden? Oder sind es nur Compiler-Autoren, die beschützend (oder faul) sind?

    – SF.

    29. Januar 2010 um 12:49 Uhr

  • Damit beide Definitionen möglich sind, benötigen Sie eine überladende Auflösung unter Berücksichtigung des Verwendungskontexts. In C gibt es keine Überladung (auf Benutzerebene). Und in C++ berücksichtigt die Überladungsauflösung nicht den Verwendungskontext (mit Ausnahme der impliziten Konvertierung).

    – Ein Programmierer

    29. Januar 2010 um 12:54 Uhr

  • @SF: Stellen Sie sich zwei Aufzählungen vor: Colors und Fruits. Was wäre der Wert von Orange?

    – mouviciel

    29. Januar 2010 um 12:55 Uhr

  • Eine Aufzählung hat in C den Typ int, es ist kein separater Typ. Einige Compiler warnen jedoch, wenn Sie es mit anderen Aufzählungen vergleichen.

    – Nr

    29. Januar 2010 um 12:56 Uhr

  • @nos “enum hat einen int-Typ” Hmmm, dachte ich enum könnte verschiedene Typen haben: Art.-Nr.

    – chux – Wiedereinsetzung von Monica

    13. April 2015 um 16:58 Uhr

Ich schlage vor, Sie verschmelzen die beiden:

enum Month {
  Jan, January=Jan, Feb, February=Feb, Mar, March=Mar, 
  Apr, April=Apr,   May,               Jun, June=Jun, 
  Jul, July=Jul,    Aug, August=Aug,   Sep, September=Sep, 
  Oct, October=Oct, Nov, November=Nov, Dec, December=Dec};

Was genau den gleichen Effekt hat und bequemer ist.

Wenn Sie möchten, dass Januar den Wert 1 anstelle von 0 hat, fügen Sie Folgendes hinzu:

enum Month {
  Jan=1, January=Jan, Feb, February=Feb, ....

Benutzeravatar von Alexander Poluektov
Alexander Poluktow

Um Namenskonflikte zu vermeiden, könnten Sie in C++ Ihre Aufzählungen in Strukturen einpacken:

struct Month { enum {January, February, March, April, May, June, July,
        August, September, October, November, December}; };
struct ShortMonth { enum {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; };

  • Ja, aber das Problem des Themenstarters tritt auch in C++ auf. Daher denke ich, dass es auch für C++-Leute nützlich sein könnte. Beitrag bearbeitet, um diese Änderung widerzuspiegeln.

    – Alexander Poluktow

    29. Januar 2010 um 13:22 Uhr

  • Oder verwenden enum class oder auch namespace

    – o11c

    26. Juni 2015 um 0:04 Uhr

In C++11 können Sie verwenden Bereichsbezogene Aufzählungen um dies zu beheben. Dadurch werden die Namen aus dem globalen Gültigkeitsbereich entfernt und auf den Aufzählungsnamen beschränkt.

enum class Identity
{
       UNKNOWN = 1,
       CHECKED = 2,
       UNCHECKED =3
};

enum class Status
{
       UNKNOWN = 0,
       PENDING = 1,
       APPROVED = 2,
       UNAPPROVED =3
};

int main ()
{
    Identity::UNKNOWN;
    Status::UNKNOW;
}

Live-Beispiel

Was Entspannung gesagt hat. Aber ich möchte auch sagen, dass Ihr Beispiel eine ziemlich ungewöhnliche Verwendung von Aufzählungen zu sein scheint. Ich kann den Wert eines ShortMonth und eines LongMonth nicht erkennen, die sich beide auf dasselbe beziehen – dies wäre für Zeichenfolgen sinnvoll, aber nicht für Aufzählungen. Warum nicht einfach einen einzigen Month-Enumerationstyp haben?

Benutzeravatar von fortran
Fortran

Mein Vorschlag hier ist, nur eine Aufzählung zu haben, da sie vom gleichen Typ sind. Wenn Sie möchten, dass kurze Aliase weniger in Ihren Code eingeben (auch wenn ich Ihnen nicht dazu raten würde), können Sie Folgendes tun:

enum Month {
 January, Jan = January,
 February, Feb = February,
 March, Mar = March,
 April, Apr = April
 May,
 June, Jun = June,
 July, Jul = July,
 ...};

Und um unterschiedliche Präsentationsnamen (kurz und lang) zu haben, sollten Sie zwei unterschiedliche String-Arrays haben, die durch die Aufzählung indiziert werden.

char[MAX_MONTH_NAME_LENGTH][12] month_long_names = {
  "January", "February", ...
}

char[3][12] short_long_names = {
  "Jan", "Feb", ...
}

printf("month %d long name is %s, and short name is %s\n", May, long_month_names[May], short_month_names[May]);

Benutzeravatar von Morfildur
Morfildur

In C werden Aufzählungen ohne Typpräfix verwendet, also schreiben Sie:

month[0] = January;  
month[4] = May;

Die Aufzählung Month und ShortMonth haben denselben Gültigkeitsbereich, sodass der Compiler nicht wissen kann, welcher May verwendet werden soll. Eine offensichtliche Lösung wäre, den Aufzählungen ein Präfix voranzustellen, aber ich bin mir nicht sicher, ob Ihre Verwendung dieser Aufzählungen in diesem Fall gerechtfertigt ist.

1394110cookie-checkZwei Aufzählungen haben einige Elemente gemeinsam, warum erzeugt dies einen Fehler?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy