84 votes

Enum vs Enum fortement typé

Je suis un débutant en programmation C++.

Aujourd'hui, j'ai découvert un nouveau sujet : les caractères fortement typés. enum . J'ai fait quelques recherches mais jusqu'à présent je n'arrive pas à savoir pourquoi nous avons besoin de cela et à quoi cela sert-il ?

Par exemple, si nous avons :

enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/

Pourquoi devons-nous écrire ?

enum class xyz{a, b, c};

Qu'essayons-nous de faire ici ? Mon doute le plus important est de savoir comment l'utiliser. Pourriez-vous me donner un petit exemple qui me permettrait de comprendre.

116voto

juanchopanza Points 115680

OK, premier exemple : les enums à l'ancienne n'ont pas leur propre champ d'application :

enum Animals {Bear, Cat, Chicken};
enum Birds {Eagle, Duck, Chicken}; // error! Chicken has already been declared!

enum class Fruits { Apple, Pear, Orange };
enum class Colours { Blue, White, Orange }; // no problem!

Deuxièmement, ils convertissent implicitement en types intégraux, ce qui peut donner lieu à des comportements étranges :

bool b = Bear && Duck; // what?

Enfin, vous pouvez spécifier le type intégral sous-jacent des enums C++11 :

enum class Foo : char { A, B, C};

Auparavant, le type sous-jacent n'était pas spécifié, ce qui pouvait entraîner des problèmes de compatibilité entre les plates-formes. Editar Il a été signalé dans les commentaires que vous pouvez également spécifier le type intégral sous-jacent d'une énumération "ancien style" en C++11.

17voto

SingerOfTheFall Points 9936

Un bon article sur les enums est disponible à l'adresse suivante cette page IBM Il est très détaillé et bien écrit. Voici quelques points importants en bref :

Les enums scopés résolvent la plupart des limitations rencontrées par les enums ordinaires : sécurité complète des types, type sous-jacent bien défini, problèmes de champ d'application et déclaration en avant.

  • La sécurité de type est obtenue en interdisant toutes les conversions implicites des enums à portée vers d'autres types.
  • Vous obtenez une nouvelle portée, et l'énumération n'est plus dans la portée englobante, ce qui permet d'éviter les conflits de noms.
  • Les enums scopés vous permettent de spécifier le type sous-jacent de l'énumération et, pour les enums scopés, le type par défaut est int si vous choisissez de ne pas le spécifier.
  • Toute énumération dont le type sous-jacent est fixe peut être déclarée à l'avance.

11voto

ForEveR Points 28133

Valeurs de enum class est vraiment du type enum class , pas underlying_type comme pour les C-enums.

enum xyz { a, b, c};
enum class xyz_c { d, f, e };

void f(xyz x)
{
}

void f_c(xyz_c x)
{
}

// OK.
f(0);
// OK for C++03 and C++11.
f(a);
// OK with C++11.
f(xyz::a);
// ERROR.
f_c(0);
// OK.
f_c(xyz_c::d);

7voto

Jnana Points 23

Les classes d'énumérations ("new enums", "strong enums") permettent de résoudre trois problèmes liés aux énumérations traditionnelles du C++ :

  1. conventionnel enums convertissent implicitement en int ce qui provoque des erreurs lorsque l'on ne veut pas qu'une énumération se comporte comme un nombre entier.
  2. conventionnel enums exportent leurs énumérateurs dans la portée environnante, ce qui entraîne des conflits de noms.
  3. Le type sous-jacent d'un enum ne peut pas être spécifié, ce qui entraîne des confusions, des problèmes de compatibilité et rend la déclaration préalable impossible.

enum class ("strong enums") sont fortement typés et cadrés :

enum Alert { green, yellow, orange, red }; // traditional enum

enum class Color { red, blue };   // scoped and strongly typed enum
                                  // no export of enumerator names into enclosing scope
                                  // no implicit conversion to int
enum class TrafficLight { red, yellow, green };

Alert a = 7;              // error (as ever in C++)
Color c = 7;              // error: no int->Color conversion

int a2 = red;             // ok: Alert->int conversion
int a3 = Alert::red;      // error in C++98; ok in C++11
int a4 = blue;            // error: blue not in scope
int a5 = Color::blue;     // error: not Color->int conversion

Color a6 = Color::blue;   // ok

Comme indiqué, les enums traditionnels fonctionnent comme d'habitude, mais vous pouvez maintenant, de manière facultative, qualifier le nom de l'enum.

Les nouvelles énumérations sont des "classes d'énumérations" parce qu'elles combinent des aspects des énumérations traditionnelles (noms, valeurs) avec des aspects des classes (membres délimités et absence de conversions).

La possibilité de spécifier le type sous-jacent permet de simplifier l'interopérabilité et de garantir la taille des énumérations :

enum class Color : char { red, blue };  // compact representation

enum class TrafficLight { red, yellow, green };  // by default, the underlying type is int

enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U };   // how big is an E?
                                                 // (whatever the old rules say;
                                                 // i.e. "implementation defined")

enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U };   // now we can be specific

Il permet également de déclarer les enums à l'avance :

enum class Color_code : char;     // (forward) declaration
void foobar(Color_code* p);       // use of forward declaration
// ...
enum class Color_code : char { red, yellow, green, blue }; // definition

Le type sous-jacent doit être l'un des types d'entiers signés ou non signés ; la valeur par défaut est int .

Dans la bibliothèque standard, enum sont utilisées :

  1. Cartographie des codes d'erreur spécifiques aux systèmes : En <system_error> : enum class errc ;
  2. Indicateurs de sécurité des pointeurs : En <memory> : enum class pointer_safety { relaxed, preferred, strict };
  3. Erreurs de flux d'E/S : En <iosfwd> : enum class io_errc { stream = 1 };
  4. Gestion des erreurs de communication asynchrones : En <future> : enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

Plusieurs d'entre eux ont des opérateurs, tels que == définis.

3voto

Ram Points 1111

Enum Scope

Les énumérations exportent leurs énumérateurs vers le champ d'application environnant. Cela présente deux inconvénients. Premièrement, cela peut entraîner des conflits de noms, si deux énumérateurs de différents enums déclarés dans la même portée portent le même nom ; deuxièmement, il n'est pas possible d'utiliser un énumérateur dont le nom est entièrement qualifié, y compris le nom de l'énumération.

enum ESet {a0, a, a1, b1, c3};
enum EAlpha{a, b, c}

select = ESet::a; // error
select = a;       // is ambigious

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X