Partager via


Avertissement du compilateur (niveau 4) C4471

« enumeration » : une déclaration anticipée d'une énumération non délimitée doit avoir un type sous-jacent (int pris par défaut)

Une déclaration de transfert d’une énumération non portée a été trouvée sans spécificateur pour le type sous-jacent. Par défaut, Visual C++ suppose qu’il s’agit int du type sous-jacent d’une énumération. Cela peut entraîner des problèmes si un type différent est utilisé dans la définition d’énumération, par exemple, si un type explicite différent est spécifié ou si un type différent est implicitement défini par un initialiseur. Vous pouvez également rencontrer des problèmes de portabilité ; D’autres compilateurs ne supposent pas que int le type sous-jacent d’une énumération est celui d’une énumération.

Cet avertissement est désactivé par défaut ; vous pouvez utiliser /Wall ou /wN4471 pour l’activer sur la ligne de commande, ou utiliser #pragma avertissement dans votre fichier source.

Exemples

Dans certains cas, cet avertissement est faux. Si une déclaration de transfert pour une énumération apparaît après la définition, cet avertissement peut se déclencher. Par exemple, ce code est valide, même s’il peut provoquer l’erreur C4471 :

// C4471a.cpp
// Compile with: cl /c /w14471 C4471a.cpp
enum Example { item = 0x80000000UL };
enum Example;    // Spurious C4471
// ...

En règle générale, il est sûr d’utiliser la définition complète d’une énumération non étendue au lieu d’une déclaration de transfert. Vous pouvez placer la définition dans un fichier d’en-tête et l’inclure dans les fichiers sources qui y font référence. Cela fonctionne dans le code écrit pour C++98 et versions ultérieures. Nous recommandons cette solution pour la portabilité et la facilité de maintenance.

// C4471b.cpp
// Compile with: cl /c /w14471 C4471b.cpp
enum Example;    // C4471
// To fix, replace the line above with the enumeration definition:
// enum Example { item = 0x80000000UL };
// ...

En C++11, vous pouvez ajouter un type explicite à une énumération non étendue et à sa déclaration de transfert. Nous vous recommandons cette solution uniquement si la logique d’inclusion d’en-tête complexe empêche l’utilisation de la définition au lieu d’une déclaration de transfert. Cette solution peut entraîner un problème de maintenance : si vous modifiez le type sous-jacent utilisé pour la définition d’énumération, vous devez également modifier toutes les déclarations de transfert à mettre en correspondance, ou vous risquez d’avoir des erreurs silencieuses dans votre code. Vous pouvez placer la déclaration en avant dans un fichier d’en-tête pour réduire ce problème.

Fichier source C4471c.cpp :

// C4471c.cpp
// Client code for enumeration defined in C4471d.cpp
// Compile with: cl /c /w14471 C4471c.cpp C4471d.cpp
enum Example;    // C4471, int assumed
// To fix, replace the lines above with the forward declarations:
// enum Example : unsigned;
// ...

Fichier source C4471d.cpp :

// C4471d.cpp
// Definition for enumeration used in C4471c.cpp
// Compile with: cl /c /w14471 C4471c.cpp C4471d.cpp
enum Example : unsigned { item = 0x80000000 }; // explicit type
// ...

Si vous spécifiez un type explicite pour une énumération, nous vous recommandons également d’activer l’avertissement C4369, activé par défaut. Cela identifie les cas où un élément d’énumération nécessite un type différent du type spécifié explicitement.

Vous pouvez modifier votre code pour utiliser une énumération délimitée, une fonctionnalité qui est nouvelle en C++11. La définition et le code client qui utilise le type d’énumération doivent être modifiés pour utiliser une énumération délimitée. Nous vous recommandons d’utiliser une énumération délimitée si vous rencontrez des problèmes de pollution de l’espace de noms, car les noms des éléments d’énumération définis sont limités à l’étendue de l’énumération. Une autre caractéristique d’une énumération étendue est que ses membres ne peuvent pas être convertis implicitement en un autre type intégral ou énumération, qui peut être une source de bogues subtils.

Fichier source C4471e.cpp :

// C4471e.cpp
// Client code for scoped enumeration defined in C4471f.cpp
// Compile with: cl /c /w14471 C4471e.cpp C4471f.cpp
enum Example;    // C4471
// To fix, replace the line above with the forward declaration:
// enum class Example;
// ...

Fichier source C4471f.cpp :

// C4471f.cpp
// Definition for scoped enumeration used in C4471e.cpp
// Compile with: cl /c /w14471 C4471e.cpp C4471f.cpp
enum class Example { item = 0 };
// ...