Share via


コンパイラの警告 (レベル 4) C4471

'enumeration': 対象範囲外の列挙の事前宣言には基になる型が必要です (int が想定されます)

スコープが設定されていない列挙型の前方宣言が、基になる型の指定子なしで見つかりました。 既定では、Visual C++ は int を列挙の基礎となる型と想定しています。 これにより、列挙型定義で異なる型が使用されている場合に問題が発生する可能性があります。例えば、異なる明示的な型が指定された場合、あるいは初期化子で暗黙的に異なる型が設定された場合などです。 また、移植性の問題もあります。他のコンパイラでは int が列挙型の基になる型であるとはみなさないからです。

この警告は既定でオフになっています。/Wall または /wN4471 を使用してコマンド ラインで有効にするか、ソース ファイルで #pragma 警告 を使用できます。

場合によっては、この警告は誤りであることがあります。 定義の後に列挙型の前方宣言がある場合、この警告が発生する可能性があります。 たとえば、C4471 が発生する可能性がある場合でも、このコードは有効です:

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

一般に、スコープされていない列挙については、前方宣言ではなく、完全な定義を使用するほうが安全です。 定義をヘッダー ファイルに含め、それを参照するソース ファイルに含めることもできます。 これは、C++98 以降用に記述されたコードで機能します。 移植性とメンテナンスの容易さのために、このソリューションをお勧めします。

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

C++11 では、スコープのない列挙体とその前方宣言に明示的な型を追加できます。 この方法は、複雑なヘッダー インクルード ロジックによって、前方宣言の代わりに定義を使用することができない場合にのみ推奨されます。 この解決策は、メンテナンスの問題を招く可能性があります。列挙の定義に使用する基礎となる型を変更する場合、すべての前方宣言も一致するように変更しなければならず、そうしないとコードにサイレント エラーが発生する可能性があります。 この問題を最小限に抑えるために、ヘッダー ファイルに前方宣言を挿入できます。

ソース ファイル 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;
// ...

ソース ファイル 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
// ...

列挙型に明示的な型を指定する場合は、既定でオンの警告 C4369 も有効にすることを推奨します。 これにより、列挙項目に明示的に指定された型とは異なる型が必要なケースが識別されます。

C++11 の新機能であるスコープ付き列挙型を使用ようにコードを変更できます。 スコープ付き列挙型を使用するには、定義と列挙型を使用するクライアント コードの両方を変更する必要があります。 名前空間の汚染に問題がある場合は、スコープ付き列挙型を使用することをお勧めします。定義された列挙項目の名前は列挙型のスコープに制限されます。 スコープ付き列挙型のもう 1 つの機能は、メンバーを別の整数型または列挙型に暗黙的に変換できない点です。これは、微妙なバグのソースになる可能性があります。

ソース ファイル 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;
// ...

ソース ファイル 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 };
// ...