Aviso do compilador (nível 4) C4471

'enumeration': uma declaração de encaminhamento de uma enumeração sem escopo deve ter um tipo subjacente (int assumido)

Uma declaração de encaminhamento de uma enumeração sem escopo foi encontrada sem um especificador para o tipo subjacente. Por padrão, o Visual C++ pressupõe que int é o tipo subjacente de uma enumeração. Isso poderá causar problemas se um tipo diferente for usado na definição da enumeração, por exemplo, se um tipo explícito diferente for especificado ou se um tipo diferente for definido implicitamente por um inicializador. Você também pode ter problemas de portabilidade; outros compiladores não pressupõem que int seja o tipo subjacente de uma enumeração.

Esse aviso está desativado por padrão; você pode usar /Wall ou /wN4471 para habilitá-lo na linha de comando como um aviso #pragma no seu arquivo de origem.

Exemplos

Em alguns casos, esse aviso é espúrio. Se uma declaração de encaminhamento para uma enumeração for exibida após a definição, esse aviso poderá ser disparado. Por exemplo, esse código é válido, embora possa causar o aviso C4471:

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

Em geral, é seguro usar a definição completa para uma enumeração não copiada em vez de uma declaração de encaminhamento. Você pode colocar a definição em um arquivo de cabeçalho e incluí-la em arquivos de origem que se referem a ela. Isso funciona em código escrito para C++98 e posterior. Recomendamos essa solução devido à portabilidade e facilidade de manutenção.

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

No C++11, você pode adicionar um tipo explícito a uma enumeração não copiada e à respectiva declaração de encaminhamento. Recomendamos essa solução somente se a lógica de inclusão de cabeçalho complexa impedir o uso da definição em vez de uma declaração de encaminhamento. Essa solução pode levar a um problema de manutenção: se você alterar o tipo subjacente usado para a definição de enumeração, você também precisará alterar todas as declarações futuras para corresponderem a ele ou poderá ter erros silenciosos em seu código. Você pode colocar a declaração de encaminhamento em um arquivo de cabeçalho para minimizar esse problema.

Arquivo de origem 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;
// ...

Arquivo de origem 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
// ...

Se você especificar um tipo explícito para uma enumeração, recomendamos que você também habilite o aviso C4369, que está ativado por padrão. Isso identifica casos em que um item de enumeração exige um tipo diferente do tipo especificado explicitamente.

Você pode alterar seu código para usar uma enumeração com escopo, um recurso que é novo no C++11. A definição e qualquer código do cliente que usa o tipo de enumeração precisa ser alterada para usar uma enumeração com escopo. Recomendamos que você use uma enumeração com escopo se tiver problemas com a poluição do namespace, pois os nomes dos itens de enumeração definidos são limitados ao escopo da enumeração. Outro recurso de uma enumeração com escopo é que os membros dela não podem ser convertidos implicitamente em outro tipo integral ou de enumeração, o que pode ser uma fonte de bugs sutis.

Arquivo de origem 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;
// ...

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