Perché usi typedef quando dichiari un enum in C ++?

Non ho scritto alcun C ++ in anni e ora sto cercando di tornarci. Ho poi trovato questo e ho pensato di rinunciare:

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

Cos’è questo? Perché la parola chiave typedef utilizzata qui? Perché il nome TokenType appare due volte in questa dichiarazione? In che modo la semantica è diversa da questa:

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

In C, dichiarare il tuo enum nel primo modo ti permette di usarlo in questo modo:

 TokenType my_type; 

Se usi il secondo stile, sarai costretto a dichiarare la tua variabile in questo modo:

 enum TokenType my_type; 

Come detto da altri, questo non fa differenza in C ++. La mia ipotesi è che sia la persona che ha scritto questo è un programmatore C nel cuore, o stai compilando il codice C come C ++. Ad ogni modo, non influenzerà il comportamento del tuo codice.

È un patrimonio di C, in C, se lo fai:

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

dovrai usarlo facendo qualcosa come:

 enum TokenType foo; 

Ma se lo fai:

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

Sarai in grado di dichiarare:

 TokenType foo; 

Ma in C ++, puoi usare solo la precedente definizione e usarla come se fosse in un typedef C.

Non hai bisogno di farlo. In C (non C ++) era necessario usare enum Enumname per fare riferimento a un elemento di dati del tipo enumerato. Per semplificarlo, ti è stato permesso digitarlo in un singolo tipo di dati.

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

funzioni consentite che prendono un parametro dell’enum da definire come

 void f( MyEnum x ) 

invece del più lungo

 void f( enum MyEnum x ) 

Nota che il nome del typename non deve essere uguale al nome dell’enum. Lo stesso succede con le strutture.

In C ++, d’altra parte, non è richiesto, poiché le enumerazioni, le classi e le strutture sono accessibili direttamente come tipi in base al loro nome.

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

In C, è un buon stile perché puoi cambiare il tipo in qualcosa oltre a un enum.

 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 ++ puoi definire l’enum in modo che si compili come C ++ o C.

Holdover da C.

Alcuni dicono che C non ha lo spazio dei nomi ma non è tecnicamente corretto. Ne ha tre:

  1. Tag ( enum e struct )
  2. etichette
  3. Globale (tutto il resto)

typedef enum { } XYZ; dichiara un’enumerazione anonima e la importa nello spazio dei nomi globale con il nome XYZ .

typedef enum ABC { } XYZ; dichiara un enum denominato ABC nello spazio dei nomi del tag, quindi lo importa nello spazio dei nomi globale come XYZ .

Lo stesso vale per lo struct namespace.

Alcune persone non vogliono disturbarsi con gli spazi dei nomi separati in modo che digitino tutto. Gli altri non digitano mai perché vogliono il namespace.

Questo è un po ‘vecchio, ma comunque, spero che apprezzerai il link che sto per scrivere come ho apprezzato quando l’ho incontrato all’inizio di quest’anno.

Eccolo. Dovrei citare la spiegazione che è sempre nella mia mente quando devo cogliere alcuni tipi di errore sgradevoli:

Nelle dichiarazioni variabili, i nomi introdotti sono istanze dei tipi corrispondenti. […] Tuttavia, quando la parola chiave typedef precede la dichiarazione, i nomi introdotti sono alias dei tipi corrispondenti

Come molte persone hanno già detto, non è necessario usare typedefs che dichiara enumerazioni in C ++ . Ma questa è la spiegazione della syntax del typedef! Spero che sia d’aiuto (Probabilmente non OP, visto che sono passati quasi 10 anni, ma chiunque stia lottando per capire questo genere di cose).

In alcune guide del codice C la versione typedef è preferita per “chiarezza” e “semplicità”. Non sono d’accordo, perché il typedef offusca la vera natura dell’object dichiarato. In realtà, non uso typedef perché quando dichiaro una variabile C voglio essere chiaro su cosa sia effettivamente l’object. Questa scelta mi aiuta a ricordare più velocemente quello che fa un vecchio pezzo di codice, e aiuterà gli altri a mantenere il codice in futuro.

La risposta effettiva alla domanda “perché” (che è sorprendentemente ignorata dalle risposte esistenti in cima a questa vecchia domanda) è che questa dichiarazione di enum si trova probabilmente in un file di intestazione che è destinato a essere compilabile come codice C e C ++ ( vale a dire incluso in entrambi i casi di implementazione C e C ++). L’arte di scrivere tali file di intestazione si basa sulla capacità dell’autore di selezionare le caratteristiche linguistiche che hanno il significato corretto compatibile in entrambe le lingue.