Condividi tramite


Avviso del compilatore (livello 4) C4471

'enumeration': una dichiarazione forward di un'enumerazione senza ambito deve avere un tipo sottostante (int presupposto)

È stata trovata una dichiarazione forward di un'enumerazione senza ambito per il tipo sottostante. Per impostazione predefinita, Visual C++ presuppone int che sia il tipo sottostante per un'enumerazione. Ciò può causare problemi se nella definizione dell'enumerazione viene usato un tipo diverso, ad esempio se viene specificato un tipo esplicito diverso o se un tipo diverso viene impostato in modo implicito da un inizializzatore. È anche possibile che si verifichino problemi di portabilità; altri compilatori non presuppongono int che sia il tipo sottostante di un'enumerazione.

Questo avviso è disattivato per impostazione predefinita; è possibile usare /Wall o /wN4471 per abilitarlo nella riga di comando oppure usare #pragma avviso nel file di origine.

Esempi

In alcuni casi, questo avviso è spurioso. Se dopo la definizione viene visualizzata una dichiarazione forward per un'enumerazione, questo avviso potrebbe essere generato. Ad esempio, questo codice è valido, anche se può causare C4471:

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

In generale, è possibile usare la definizione completa per un'enumerazione senza ambito anziché una dichiarazione forward. È possibile inserire la definizione in un file di intestazione e includerla nei file di origine che vi fanno riferimento. Funziona nel codice scritto per C++98 e versioni successive. È consigliabile usare questa soluzione per la portabilità e la facilità di manutenzione.

// 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 };
// ...

In C++11 è possibile aggiungere un tipo esplicito a un'enumerazione senza ambito e alla relativa dichiarazione di inoltro. Questa soluzione è consigliabile solo se la logica di inclusione di intestazioni complesse impedisce l'uso della definizione anziché di una dichiarazione forward. Questa soluzione può causare un problema di manutenzione: se si modifica il tipo sottostante usato per la definizione dell'enumerazione, è necessario modificare anche tutte le dichiarazioni di inoltro in modo che corrispondano o che si verifichino errori invisibile all'utente nel codice. È possibile inserire la dichiarazione in avanti in un file di intestazione per ridurre al minimo questo problema.

C4471c.cppFile di origine :

// 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;
// ...

C4471d.cppFile di origine :

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

Se si specifica un tipo esplicito per un'enumerazione, è consigliabile abilitare anche l'avviso C4369, che è attivato per impostazione predefinita. In questo modo vengono identificati i casi in cui un elemento di enumerazione richiede un tipo diverso rispetto al tipo specificato in modo esplicito.

È possibile modificare il codice in modo da usare un'enumerazione con ambito, una funzionalità nuova in C++11. Sia la definizione che il codice client che usa il tipo di enumerazione devono essere modificati per usare un'enumerazione con ambito. È consigliabile usare un'enumerazione con ambito se si verificano problemi con l'inquinamento dello spazio dei nomi, poiché i nomi degli elementi di enumerazione definiti sono limitati all'ambito dell'enumerazione. Un'altra funzionalità di un'enumerazione con ambito è che i relativi membri non possono essere convertiti in modo implicito in un altro tipo integrale o di enumerazione, che può essere una fonte di bug sottili.

C4471e.cppFile di origine :

// 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;
// ...

C4471f.cppFile di origine :

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