221 Stimmen

Warum verwendet man typedef, wenn man ein enum in C++ deklariert?

Ich habe seit Jahren kein C++ mehr geschrieben, und jetzt versuche ich, wieder einzusteigen. Dann bin ich auf das hier gestoßen und dachte daran, aufzugeben:

typedef enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

Was ist das? Warum ist die typedef Schlüsselwort hier verwendet? Warum ist der Name TokenType zweimal in dieser Erklärung erscheinen? Wie unterscheidet sich die Semantik von dieser:

enum TokenType
{
    blah1 = 0x00000000,
    blah2=0x01000000,
    blah3=0x02000000
};

183voto

Ryan Fox Punkte 9794

In C können Sie Ihr Enum auf die erste Weise deklarieren und es so verwenden:

TokenType my_type;

Wenn Sie den zweiten Stil verwenden, sind Sie gezwungen, Ihre Variable wie folgt zu deklarieren:

enum TokenType my_type;

Wie bereits von anderen erwähnt, macht dies in C++ keinen Unterschied. Ich vermute, dass entweder die Person, die dies geschrieben hat, im Herzen ein C-Programmierer ist, oder Sie kompilieren C-Code als C++. So oder so, es wird das Verhalten Ihres Codes nicht beeinflussen.

18 Stimmen

Ihre Frage ist nur für C richtig, aber nicht für C++. In C++ können Enums und Structs direkt verwendet werden, als ob es einen Typedef gäbe.

8 Stimmen

Nun, ja, aber das beantwortet die eigentliche Frage, die gestellt wurde, nämlich: "Was bedeutet das überhaupt?"

0 Stimmen

Ist dies also technisch gesehen ein Typedef oder ein Enum?

116voto

mat Punkte 12303

Es ist ein C-Erbe, in C, wenn Sie :

enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
};

müssen Sie es verwenden, indem Sie etwas wie :

enum TokenType foo;

Aber wenn Sie dies tun :

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

Sie können sich anmelden:

TokenType foo;

In C++ können Sie jedoch nur die erstgenannte Definition verwenden, und zwar so, als ob sie in einem C-Typedef stünde.

1 Stimmen

Was Sie sagen, ist in C wahr. Es ist nicht wahr in C++.

62 Stimmen

Ist es nicht das, was ich in meinem letzten Satz gesagt habe?

5 Stimmen

@mat Ich habe Ihren Kommentar zum letzten Satz hochgestuft, aber um fair zu sein, er ist schlecht formuliert und verwirrend.

27voto

Sie müssen es nicht tun. In C (nicht C++) waren Sie verpflichtet, die enum Enumname um auf ein Datenelement des Aufzählungstyps zu verweisen. Zur Vereinfachung durften Sie typedef auf einen einzigen Namensdatentyp.

typedef enum MyEnum { 
  //...
} MyEnum;

erlaubte es, Funktionen, die einen Parameter der Aufzählung annehmen, zu definieren als

void f( MyEnum x )

anstelle des längeren

void f( enum MyEnum x )

Beachten Sie, dass der Name des Typnamens nicht mit dem Namen der Aufzählung übereinstimmen muss. Das Gleiche gilt für structs.

In C++ hingegen ist dies nicht erforderlich, da auf Enums, Klassen und Structs als Typen direkt über ihren Namen zugegriffen werden kann.

// C++
enum MyEnum {
   // ...
};
void f( MyEnum x ); // Correct C++, Error in C

1 Stimmen

Ich denke, dass dies eine bessere Antwort ist als die allgemein akzeptierte, da sie klar erklärt, "warum" es anders ist.

16voto

russbishop Punkte 15620

Manche Leute sagen, dass C keine Namensräume hat, aber das ist technisch nicht korrekt. Es hat drei:

  1. Tags ( enum , union et struct )
  2. Etiketten
  3. (alles andere)

typedef enum { } XYZ; deklariert eine anonyme Aufzählung und importiert sie in den globalen Namespace mit dem Namen XYZ .

typedef enum ABC { } XYZ; deklariert eine Aufzählung namens ABC im Tag-Namensraum und importiert es dann in den globalen Namensraum als XYZ .

Manche Leute wollen sich nicht mit den separaten Namespaces herumschlagen und typisieren alles. Andere typisieren nie, weil sie den Namespacing wollen.

1 Stimmen

Das ist nicht ganz richtig. structs, unions und enums werden über den Tag-Namen referenziert (es sei denn, sie sind anonym, wie Sie erwähnt haben). Es gibt getrennte Namespaces für Typen und Tags. Sie können einen Typ mit genau demselben Namen wie ein Tag haben und problemlos kompilieren. Wenn jedoch eine Enum den gleichen Tag wie ein struct hat, ist dies ein Kompilierfehler, genau wie 2 structs oder 2 enums mit dem gleichen Tag. Sie vergessen auch, dass Labels für goto ein separater Namespace sind. Ein Label kann denselben Namen wie ein Tag oder ein Bezeichner haben, aber keinen Typ, und ein Bezeichner kann denselben Namen wie ein Tag haben, aber keinen Typ.

14voto

BeWarned Punkte 2252

In C ist das ein guter Stil, weil man den Typ in etwas anderes als eine Aufzählung ändern kann.

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

foo(enum e_TokenType token);  /* this can only be passed as an enum */

foo(TokenType token); /* TokenType can be defined to something else later
                         without changing this declaration */

In C++ können Sie das Enum so definieren, dass es als C++ oder C kompiliert werden kann.

0 Stimmen

Willst du damit nicht sagen In C++ you can *typedef* the enum so that it will compile as C++ or C. ? Sie sagten: In C++ you can define the enum so that it will compile as C++ or C. Beachten Sie, wie ich Ihre define a typedef . Nun...ich nehme an typedef ing es definieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X