Share via


Advertencia del compilador (nivel 4) C4471

"enumeration": una declaración de reenvío de una enumeración sin ámbito debe tener un tipo subyacente (se presupone int)

Se encontró una declaración de reenvío de una enumeración sin ámbito sin un especificador para el tipo subyacente. De forma predeterminada, Visual C++ supone que int es el tipo subyacente de una enumeración. Esto puede causar problemas si se usa un tipo diferente en la definición de enumeración, por ejemplo, si se especifica un tipo explícito diferente o si un inicializador establece implícitamente un tipo diferente. También puede tener problemas de portabilidad. Otros compiladores no suponen que int sea el tipo subyacente de una enumeración.

Esta advertencia está desactivada de forma predeterminada; Puede usar /Wall o /wN4471 para habilitarlo en la línea de comandos, o usar #pragma warning en el archivo de código fuente.

Ejemplos

En algunos casos, esta advertencia es falsa. Si aparece una declaración de reenvío para una enumeración después de la definición, esta advertencia podría producirse. Por ejemplo, este código es válido, aunque puede provocar C4471:

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

En general, usar la definición completa para una enumeración sin ámbito en lugar de una declaración de reenvío es seguro. Puede colocar la definición en un archivo de encabezado e incluirla en los archivos de código fuente que le hacen referencia. Esto funciona en código escrito para C++98 y versiones posteriores. Se recomienda esta solución por la portabilidad y la facilidad de mantenimiento.

// 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, puede agregar un tipo explícito a una enumeración sin ámbito y a su declaración de reenvío. Se recomienda esta solución solo si la lógica compleja de inclusión de encabezados impide el uso de la definición en lugar de una declaración de reenvío. Esta solución puede dar lugar a un problema de mantenimiento: si cambia el tipo subyacente usado para la definición de enumeración; también debe cambiar todas las declaraciones de reenvío para que coincidan, o puede que tenga errores silenciosos en el código. Puede colocar la declaración de reenvío en un archivo de encabezado para minimizar este problema.

Archivo de origen 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;
// ...

Archivo de origen 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 especifica un tipo explícito para una enumeración, también se recomienda habilitar la advertencia C4369, que está activa de forma predeterminada. Esto identifica los casos en los que un elemento de enumeración requiere un tipo diferente del especificado explícitamente.

Puede cambiar el código para usar una enumeración con ámbito, una característica que es nueva en C++11. Tanto la definición como cualquier código de cliente que use el tipo de enumeración deben cambiarse para usar una enumeración con ámbito. Se recomienda usar una enumeración con ámbito si tiene problemas con la contaminación del espacio de nombres, ya que los nombres de los elementos de enumeración definidos están limitados al ámbito de la enumeración. Otra característica de una enumeración con ámbito es que sus miembros no se pueden convertir implícitamente a otro tipo entero o de enumeración, lo que puede ser una fuente de errores sutiles.

Archivo de origen 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;
// ...

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