Waarom gebruik je typedef bij het declareren van een enum in C++?

Ik heb al jaren geen C++ meer geschreven en nu probeer ik er weer in te komen. Ik kwam dit tegen en dacht erover om het op te geven:

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

Wat is dit? Waarom wordt hier het trefwoord typedefgebruikt? Waarom komt de naam TokenTypetwee keer voor in deze aangifte? Waarin verschilt de semantiek hiervan:

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

Antwoord 1, autoriteit 100%

In C, als je je opsomming op de eerste manier declareert, kun je het als volgt gebruiken:

TokenType my_type;

Als je de tweede stijl gebruikt, moet je je variabele als volgt declareren:

enum TokenType my_type;

Zoals door anderen al vermeld, maakt dit geen verschil in C++. Mijn gok is dat ofwel de persoon die dit heeft geschreven een C-programmeur in hart en nieren is, of dat je C-code compileert als C++. Hoe dan ook, het heeft geen invloed op het gedrag van je code.


Antwoord 2, autoriteit 65%

Het is een C-erfenis, in C, als je dat doet:

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

je moet het gebruiken om iets te doen als:

enum TokenType foo;

Maar als je dit doet:

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

U kunt aangeven:

TokenType foo;

Maar in C++ kun je alleen de vorige definitie gebruiken en deze gebruiken alsof het een C-typedef is.


Antwoord 3, autoriteit 13%

U hoeft het niet te doen. In C (niet C++) moest je enum Enumnamegebruiken om te verwijzen naar een data-element van het opgesomde type. Om het te vereenvoudigen, mocht je het typedefiniërennaar een gegevenstype met één naam.

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

sta toe dat functies die een parameter van de enum nemen worden gedefinieerd als

void f( MyEnum x )

in plaats van de langere

void f( enum MyEnum x )

Merk op dat de naam van de typenaam niet gelijk hoeft te zijn aan de naam van de enum. Hetzelfde gebeurt met structs.

In C++ is het daarentegen niet vereist, omdat opsommingen, klassen en structs direct als typen op hun naam kunnen worden benaderd.

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

Antwoord 4, autoriteit 7%

In C is het een goede stijl omdat je het type kunt veranderen in iets anders dan een opsomming.

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++ kun je de enum definiëren zodat deze wordt gecompileerd als C++ of C.


Antwoord 5, autoriteit 4%

Holdover van C.


Antwoord 6, autoriteit 4%

Sommige mensen zeggen dat C geen naamruimten heeft, maar dat is technisch niet correct. Het heeft drie:

  1. Tags (enum, unionen struct)
  2. Labels
  3. (al het andere)

typedef enum { } XYZ;declareert een anonieme opsomming en importeert deze in de globale naamruimte met de naam XYZ.

typedef enum ABC { } XYZ;declareert een opsomming met de naam ABCin de tagnaamruimte en importeert deze vervolgens in de algemene naamruimte als XYZ.

Sommige mensen willen zich niet druk maken over de aparte naamruimten, dus typen ze alles in. Anderen typen nooit omdat ze de naamruimte willen.


Antwoord 7, autoriteit 2%

Dit is een beetje oud, maar ik hoop dat je de link die ik op het punt sta te typen zult waarderen, zoals ik hem op prijs stelde toen ik hem eerder dit jaar tegenkwam.

Hier het is. Ik zou de uitleg moeten citeren die altijd in mijn gedachten is als ik een paar vervelende typedefs moet begrijpen:

In variabele declaraties zijn de geïntroduceerde namen instanties van de corresponderende typen. […]
Wanneer het sleutelwoord typedefechter voorafgaat aan de declaratie, zijn de geïntroduceerde namen aliassen van de overeenkomstige typen

Zoals veel mensen eerder zeiden, is het niet nodig om typedefs te gebruiken die enums declareren in C++. Maar dat is de verklaring van de syntaxis van het typedef! Ik hoop dat het helpt (waarschijnlijk niet OP, aangezien het bijna 10 jaar geleden is, maar iedereen die moeite heeft om dit soort dingen te begrijpen).


Antwoord 8

In sommige C-codestijlgidsen wordt gezegd dat de typedef-versie de voorkeur heeft voor “duidelijkheid” en “eenvoud”.
Ik ben het daar niet mee eens, omdat het typedef de ware aard van het gedeclareerde object verdoezelt. In feite gebruik ik geen typedefs omdat ik bij het declareren van een C-variabele duidelijk wil zijn over wat het object eigenlijk is.
Deze keuze helpt mezelf om sneller te onthouden wat een oud stuk code eigenlijk doet, en zal anderen helpen bij het onderhouden van de code in de toekomst.


Antwoord 9

Het eigenlijke antwoord op de “waarom”-vraag (die verrassend wordt genegeerd door de bestaande antwoorden boven deze oude vraag) is dat deze enum-declaratie zich waarschijnlijk in een headerbestand bevindt dat bedoeld is om cross-compileerbaar als zowel C- als C++-code (dwz opgenomen in zowel C- als C++-implementatiebestanden). De kunst van het schrijven van dergelijke headerbestanden is afhankelijk van het vermogen van de auteur om taalkenmerken te selecteren die de juiste compatibele betekenis hebben in beide talen.

Other episodes