6

プロジェクトのどこかで最近見つけたコード構造を見てみましょう。

namespace Test
{
    enum EName
    {
        CoolEnum,
        NiceEnum
    };

    enum CoolEnum
    {
        CoolVal1,
        CoolVal2
    };

    enum NiceEnum
    {
        NiceVal1,
        NiceVal2
    };
}

私の質問は、なぜコンパイラがこのようなことを許可するのかということです。ここでコードサンプルを見てみましょう:

Test::CoolEnum cEnum = Test::NiceVal1; // INVALID, as compiler refers to Test::CoolEnum value of Test::Ename enum

なぜそのような混乱が許されるのですか?enumキーワードを付加する必要がある理由を理解しているので、コンパイラは、同じ名前空間内の他のenumの値を使用せずに、指定されたenumの変数を宣言していることを明確に認識します。そもそもなぜそのような構造を作ることができるのか、私にはわかりません。

4

2 に答える 2

8

C ++ 11の列挙型クラスは、これに対する解決策です。

namespace Test
{
    enum class EName
    {
        CoolEnum,
        NiceEnum
    };

    enum class CoolEnum
    {
        NiceVal1,
        NiceVal2
    };

    enum class NiceEnum
    {
        NiceVal1,
        NiceVal2
    };
}

次に、適切なものを使用できますNiceVal1

Test::CoolEnum cEnum = Test::CoolEnum::NiceVal1;

プレーン列挙型は、名前空間が何であるかという概念がないCから継承されました。プレーンな列挙型が何らかの名前空間を導入した場合、列挙型を使用するCコードはまったくコンパイルされません。そのため、下位互換性を壊さないために列挙型クラスが導入されました。

于 2012-07-06T14:05:05.347 に答える
1

答えは、標準がこの動作を規定しているためです。3.3.7/2を参照してください。

クラス名(9.1)または列挙名(7.2)は、同じスコープで宣言されたオブジェクト、関数、または列挙子の名前で非表示にすることができます。クラスまたは列挙型の名前とオブジェクト、関数、または列挙型が同じスコープで(任意の順序で)同じ名前で宣言されている場合、オブジェクト、関数、または列挙型の名前が表示されている場所では、クラスまたは列挙型の名前が非表示になります。

おそらくこれは、長い間確立されてきたCのメカニズム(列挙子が新しいスコープを開かない)との互換性を促進するためです。

あなたの場合、少なくともg ++ではtypename、列挙子(typename Test::CoolEnum cEnum = Test::NiceVal1;)の代わりに型を使用することを示すために使用できます。

ただし、一般的には、これらの衝突を完全に防ぐために、すべての列挙を別の名前空間またはクラスでスコープするのが好きです。

于 2012-07-06T15:02:56.763 に答える