web-dev-qa-db-fra.com

Pourquoi utilisez-vous typedef pour déclarer une énumération en C ++?

Je n'ai pas écrit de C++ depuis des années et maintenant j'essaye d'y revenir. J'ai alors couru à travers cela et pensé à abandonner:

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

Qu'est-ce que c'est? Pourquoi le mot clé typedef est-il utilisé ici? Pourquoi le nom TokenType apparaît-il deux fois dans cette déclaration? Comment la sémantique diffère-t-elle de ceci:

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

En C, déclarer votre enum de la première façon vous permet de l'utiliser de la manière suivante:

TokenType my_type;

Si vous utilisez le second style, vous serez obligé de déclarer votre variable comme ceci:

enum TokenType my_type;

Comme mentionné par d'autres, cela ne fait aucune différence en C++. Mon hypothèse est que la personne qui a écrit ceci est un programmeur C au cœur ou que vous compilez du code C en tant que C++. Dans les deux cas, cela n'affectera pas le comportement de votre code.

147
Ryan Fox

C'est un héritage C, en C, si vous le faites:

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

vous devrez l'utiliser pour faire quelque chose comme:

enum TokenType foo;

Mais si vous faites ceci:

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

Vous pourrez déclarer:

TokenType foo;

Mais en C++, vous pouvez utiliser uniquement la définition précédente et l’utiliser comme si elle était dans un C typedef.

91
mat

Vous n'avez pas besoin de le faire. En C (pas C++), vous deviez utiliser enum Enumname pour faire référence à un élément de données du type énuméré. Pour simplifier, il vous était permis de typedef le à un seul type de données.

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

fonctions autorisées prenant un paramètre de l'énum à définir comme

void f( MyEnum x )

au lieu du plus long

void f( enum MyEnum x )

Notez que le nom du typename n'a pas besoin d'être égal au nom de l'énum. La même chose arrive avec les structs.

En revanche, en C++, cela n’est pas obligatoire, car les énumérations, les classes et les structures sont directement accessibles en tant que types par leur nom.

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

En C, c'est un bon style car vous pouvez changer le type en quelque chose en plus d'une énumération.

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 */

En C++, vous pouvez définir l'énum pour qu'il se compile en C++ ou C.

10
BeWarned

Holdover de C.

6
Tim

Certaines personnes disent que C n’a pas d’espace de nommage mais que ce n’est pas techniquement correct. Il en a trois:

  1. Tags (enum, union et struct)
  2. Étiquettes
  3. (tout le reste)

typedef enum { } XYZ; déclare une énumération anonyme et l'importe dans l'espace de noms global sous le nom XYZ.

typedef enum ABC { } XYZ; déclare une énumération nommée ABC dans l'espace de noms de balises, puis l'importe dans l'espace de noms global sous la forme XYZ.

Certaines personnes ne veulent pas s'embarrasser des espaces de noms séparés, alors elles tapent tout. D'autres ne dactylographient jamais parce qu'ils veulent le nompacing.

5
russbishop

C'est un peu vieux, mais enfin, j'espère que vous apprécierez le lien que je vais taper comme je l'ai apprécié quand je l'ai trouvé plus tôt cette année.

Ici c'est . Je devrais citer l'explication qui me trotte toujours dans la tête lorsque je dois saisir quelques problèmes de typage méchants:

Dans les déclarations de variable, les noms introduits sont des instances des types correspondants. [...] Cependant, lorsque le mot clé typedef précède la déclaration, les noms introduits sont des alias des types correspondants.

Comme beaucoup de gens l'ont déjà dit, il n'est pas nécessaire d'utiliser les typedefs déclarant des enums en C++ . Mais c'est l'explication de la syntaxe du typedef! J'espère que cela aide (probablement pas OP, puisque cela fait presque 10 ans, mais quiconque a du mal à comprendre ce genre de choses).

3
Francisco Orlandini

La réponse réelle à la question "pourquoi" (qui est étonnamment ignorée par les réponses existantes en haut de cette ancienne question) est que cette déclaration enum se trouve probablement dans un fichier d'en-tête destiné à être compilable de manière croisée en tant que C et le code C++ (c'est-à-dire inclus dans les fiules d'implémentation C et C++). L’art d’écrire de tels fichiers d’en-tête repose sur la capacité de l’auteur à sélectionner des fonctionnalités linguistiques qui ont la signification compatible dans les deux langues.

1
AnT

Dans certains guides de style de code C, on dit que la version typedef est préférée pour "clarté" et "simplicité". Je ne suis pas d'accord, car typedef masque la nature réelle de l'objet déclaré. En fait, je n'utilise pas de typedefs parce que lorsque je déclare une variable C, je veux être clair sur ce qu'est réellement l'objet. Ce choix m'aide à me souvenir plus rapidement de ce que fait un vieux morceau de code et aidera les autres lors de la maintenance du code à l'avenir.

1
AdRiX