12

私は現在、名前空間付きの列挙型または静的定数の名前空間付きのグループが望ましいかどうかという問題について考えています。デフォルトの選択は何ですか?またその理由は何ですか?

オプション1:

namespace Direction
{
    enum Direction
    {
        north,
        east,
        south,
        west,
    };
}

オプション 2:

namespace Direction
{
    static const unsigned char north = 0;
    static const unsigned char east = 1;
    static const unsigned char south = 2;
    static const unsigned char west = 3;
}

どちらにも長所と短所があります。

プロ列挙:

  1. いくつかのタイプセーフ:

    void foo(Direction dir); // the compiler won't allow you to just pass an int or a value of an unrelated enum without explicitly casting it
    

対照列挙:

  1. 型の安全性はかなり制限されています:

    enum A
    {
        Entry1 = 1
    };
    
    enum B
    {
        Entry2 = 10
    };
    
    A a;
    if(a == Entry2)
        ; // ouch!
    
  2. int 以外の型はサポートされていません - C++ 11 より前では、long long、short、または char などの列挙型を持つことはできません。

  3. 列挙型の名前空間は最適ではありません

    1. 列挙型を別の名前空間にラップしないと、そのすべてのメンバーが周囲の名前空間を汚染します。

    2. 列挙型を別の名前空間にラップする場合、列挙型自体を型として使用すると冗長性が得られます。次に、Direction::Direction の方法で方向変数を宣言する必要があります (「Direction:: を使用しない場合」方向"、これにより、外側の名前空間が再び汚染され(最後に、 using ディレクティブが有効になるコードのその部分で)、北だけでなく方向::北の方法でそのメンバーの名前を付けることができます

プロ静的定数:

  1. C++ 11 より前の C++ での型サポートの向上 - たとえば、定数に unsigned char などの型を使用できます
  2. 適切なスコープ - using ディレクティブを介して明示的に要求することなく、外側の名前空間を汚染しません (その場合でも限られたスコープでのみ)

対照的な静的定数:

  1. 列挙型よりも型安全性がさらに低くなります。次のような関数プロトタイプを宣言することはできなくなりました。

    void foo(Direction dir);
    

    ただし、次の方法で行う必要があります。

    void foo(unsigned char dir); // now each variable of type unsigned char or of a type that can implicitly be casted into unsigned char can be passed, even if its totally unrelated to the expected "enumeration" or if the value does not match the value of any of the expected consts
    

編集: ここで、列挙型の型安全性の制限に関する興味深い記事を見つけました: http://www.drdobbs.com/enumerations/184401797

4

3 に答える 3

2

大きな違いはタイピングです。列挙型には個別の型があります。static const には既存の整数型が必要です (ただし、他の場所で使用できます)。どちらが望ましいかは、必要なものによって異なります。 の場合、Directionおそらく一意の型が必要であり、列挙型が望ましいです。他の場合では、配列の次元など、整数型の名前付き定数が本当に必要です。そのような場合、 static const がおそらく好ましいでしょう。

于 2013-11-08T18:20:19.080 に答える
1

C++11は、厳密に型指定された列挙型と改善されたスコープによって、すべての反対列挙型ポイントを解決します。

基本方向の例のような固定値のセットについては、enum を使用します。

于 2013-11-08T18:21:25.920 に答える
1

列挙型を使用すると、概念に属するすべての定数を (という名前の一意の c++ 識別子を使用してenum) 結び付けることができます。

static_castHerb Sutter は、C キャストの代わりに新しいスタイルのキャスト ( ) を好むことについて書いています。彼の議論の 1 つ (とりわけ) は、ソース コード内の正規表現でそれらを見つけることができるというものでした。

質問に戻ると、enumコードベースを grep して、一緒に使用することを意図した定数の出現を見つけることができることを意味します。これは、名前空間の定数では不可能です。

于 2013-11-08T18:58:31.643 に答える