web-dev-qa-db-fra.com

Que signifie «énumération statique» en C ++?

Je suis récemment tombé sur ceci:

static enum Response{
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};

Il compile et fonctionne sous Microsoft VS2005. Cependant, je ne suis pas sûr de ce que le modificateur "statique" est censé faire. Est-ce différent des suivants?

enum Response {
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};
32
Marcin K

Ce code exact, avec juste les points de suspension supprimés, n'est pas C++ valide. Vous ne pouvez pas utiliser le spécificateur de classe de stockage static dans une déclaration enum; cela n'a aucun sens (seuls les objets, les fonctions et les unions anonymes peuvent être déclarés static).

Vous pouvez cependant déclarer une enum et une variable tout en une déclaration:

static enum Response {
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
} x; 

Le static ici s'applique à x et c'est en fait la même chose que si vous aviez dit:

enum Response { 
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
};

static Response x;
57
James McNellis

Étonnamment, vous pouvez également y mettre d'autres spécificateurs-décl.
Cela se compile très bien dans VS2008:

auto const enum TestEnum {
    Why,
    Does
};

register volatile enum TestEnum2 {
    This,
    Work
};

Mais cela n'a aucun sens :)

Je soupçonne que le problème ici est dans l'analyse, car un code comme celui-ci:

enum TestEnum3 { Hello, World };  // Define enum
enum TestEnum3 x = World;         // Use enum

Pourrait également s'écrire:

enum TestEnum3 { Hello, World } x = World; // Define and use enum.

Fait intéressant, je remarque que si vous faites cela dans VS2008:

enum TestEnum3 { Hello, World };
const enum TestEnum3 e3 = World;
const enum TestEnum4 { F, M, L } e4 = F;

e3 = Hello; // error C2166: l-value specifies const object (Good!)
e4 = M;     // NO ERROR here though - why?

Ils ne sont donc pas équivalents comme dans le TestEnum4 cas où il semble jeter le constdécl-spécificateur. Tout est très étrange.

14
GrahamS
static enum Response { /*... */ };

Vous ne pouvez pas définir static enum en C++. static ne peut être que la variable de l'énumération, pas le type lui-même!

Compilation de votre code avec GCC version 4.3.4, cela donne cette erreur:

prog.cpp: 7: erreur: une classe de stockage ne peut être spécifiée que pour les objets et les fonctions

Rendez-vous en ligne sur ideone: http://www.ideone.com/cI1bt

Je pense que cela dit tout.

-

Cependant, si vous souhaitez limiter le type enum Response dans sa propre unité de traduction, vous pouvez utiliser un espace de noms sans nom. Jetez un œil à ce sujet:

Supériorité de l'espace de noms sans nom sur statique?

7
Nawaz

Standard

C++ 11 N3337 standard draft L'annexe C 7.1.1 dit qu'elle était autorisée en C mais n'avait aucun effet et devenait illégale en C++:

Modification: en C++, les spécificateurs statiques ou externes ne peuvent être appliqués qu'aux noms d'objets ou de fonctions. L'utilisation de ces spécificateurs avec des déclarations de type est illégale en C++. En C, ces spécificateurs sont ignorés lorsqu'ils sont utilisés sur les déclarations de type. Exemple:

static struct S {    // valid C, invalid in C++
  int i;
};

Justification: Les spécificateurs de classe de stockage n'ont aucune signification lorsqu'ils sont associés à un type. En C++, les membres de classe peuvent être déclarés avec le spécificateur de classe de stockage statique. Autoriser les spécificateurs de classe de stockage sur les déclarations de type peut rendre le code déroutant pour les utilisateurs.

Et comme struct, enum est aussi une déclaration de type.

Justification de la mise en œuvre

Les définitions d'énumération n'ont pas de stockage et ne génèrent pas de symboles dans les fichiers objets comme les variables et les fonctions. Essayez simplement de compiler et de décompiler:

struct S { int i; int j; };
int i;

avec:

g++ -c main.c
nm main.o

et vous verrez qu'il n'y a pas de symbole S, mais il y a un symbole i.

Lorsque le compilateur voit une valeur d'énumération, il l'insère simplement littéralement dans le code compilé. Cela ne fonctionne bien sûr que parce qu'il s'agit de constantes au moment de la compilation.

Ils doivent donc être inclus dans les fichiers d'en-tête.

Voir également:

En C #:

Le ';' est facultatif pour la compatibilité descendante après le bloc enum. Il ne pas permet une telle sémantique dans cette langue pour les types nommés. statique, public, etc. ont une attention particulière. L'espace de noms ne peut pas contenir de membres tels que des champs ou des méthodes.

Nécessite une balise:

ArgTypes var = ArgTypes.CUT;

En C/C++:

A besoin ';' à la fin du bloc enum. Pour les variables d'espace de noms globales, les énumérations, etc. statique est par défaut.

int type;

typedef enum {
  TOKENIZE,
  CUT
} ArgTypes;
type = TOKENIZE;  /* <ArgTypes>::TOKENIZE */
type = ArgTypes::CUT;

// Recommended Use
enum ArgTypes {
  TOKENIZE,
  CUT
};  /* Same as above */

enum Test {
  TOKENIZE,
  CUT
} ArgTypes;
type = ArgTypes::TOKENIZE;
type = CUT;   /* Assign type =>  <Test>.CUT */
type = Test::CUT;

enum {
  TOKENIZE,
  CUT
} ArgTypes;  /* Unamed.. requires tag */
type = TOKENIZE; /* <unamed>.TOKENIZE=0 => #define TOKENIZE 0*/
type = ArgTypes::TOKENIZE;  /* ** ERROR ** */
1
Latency

Je ne sais pas pourquoi statique a été utilisé ou pourquoi il compile même. Devrait juste être une réponse enum. Les énumérateurs ne sont pas des données statiques.

0
JonH