Enums scopés en C++ : pourquoi enum class est-il plus sûr que l'ancien enum ?

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi enum class est votre nouveau meilleur ami en C++ ?



Quiconque a commencé à apprendre le C++ ou y est revenu après une pause se retrouve tôt ou tard face à un dilemme : utiliser le bon vieux enum ou son cousin plus moderne enum class ? Sur Stack Overflow, la question « Why is enum class considered safer to use than plain enum? » a recueilli des milliers de vues — et ce n'est pas un hasard. Passer au scoped enum (c'est ainsi que enum class est officiellement appelé) n'est pas simplement une question de mode, mais un véritable pas vers un code plus fiable et plus lisible.



Voyons en quoi réside exactement le danger de l'ancien enum et comment enum class permet d'éviter toute une classe d'erreurs. Si vous écrivez en C++ et utilisez encore enum sans portée, cet article est pour vous.



Top 3 des erreurs de l'ancien enum (et comment enum class les corrige)



1️⃣ Pollution de l'espace de noms global



Le problème le plus courant de l'ancien enum est que ses constantes « débordent » dans l'espace de noms environnant. Imaginez que vous ayez deux énumérations :



// Mauvais : ancien enumenum Color { Red, Green, Blue };enum Feeling { Happy, Sad, Blue }; // Erreur de compilation ! Blue est déjà défini


La constante Blue de Color est déjà prise, et vous ne pouvez pas utiliser le même nom dans Feeling. Dans un grand projet avec des centaines de fichiers, cela devient un véritable casse-tête. Vous devez inventer des noms longs comme Color_Blue ou COLOR_BLUE, ce qui enlaidit le code.



Solution avec enum class :



// Bien : enum class (scoped enum)enum class Color { Red, Green, Blue };enum class Feeling { Happy, Sad, Blue }; // OK ! Pas de conflit


Maintenant, Blue vit à l'intérieur de sa classe. Pour y accéder, il faut écrire Color::Blue ou Feeling::Blue. Cela résout non seulement le problème des collisions, mais rend également le code auto-documenté — on voit immédiatement à quel type appartient la valeur.



2️⃣ Conversion implicite en int (et inversement)



L'ancien enum se convertit implicitement en types entiers. À première vue, c'est pratique, mais en pratique, c'est une source de bugs difficiles à détecter.



// Ancien enum dangereuxenum WarningLevel { Low, Medium, High };

void setVolume(int level) { if (level > 10) level = 10; // ...}

setVolume(High); // Ça marche ! Mais High = 2, pas un niveau de volume// Vous avez accidentellement passé un niveau d'alerte au lieu du volume — le compilateur ne dit rien


Le compilateur avalera cela sans le moindre avertissement. Et si vous inversez l'ordre des arguments dans une fonction — le bug passera en runtime.



Comment enum class protège :



enum class WarningLevel { Low, Medium, High };

void setVolume(int level);

setVolume(WarningLevel::High); // Erreur de compilation !// Pas de conversion implicite de enum class vers int


Le compilateur vous obligera à convertir explicitement la valeur si cela est vraiment nécessaire. Cela signifie que vous êtes conscient de chaque conversion, plutôt que de compter sur « peut-être que ça passera ».



// Si vraiment nécessaire — on le fait explicitementsetVolume(static_cast<int>(WarningLevel::High)); // Explicite et clair


3️⃣ Type de base indéfini



L'ancien enum ne garantit pas quel type entier sera utilisé en interne. Le compilateur le choisit lui-même (généralement int), ce qui peut entraîner des surprises lors du transfert entre différents compilateurs ou plateformes.



// La taille peut varier !enum Small { A, B, C }; // Peut être int, peut être charenum Big { X = 100000, Y, Z }; // Peut encore être int


Avec enum class, vous pouvez spécifier explicitement le type de base, ce qui vous donne un contrôle total

Blogs

Book Recommendations