10

Windows の CreateWindow(...style | style,...) のようなフラグを持つ関数、たとえば createnum 関数を作成するにはどうすればよいでしょうか。

int CreateNum(flag flags) //???
{
    int num = 0;
    if(flags == GREATER_THAN_TEN)
        num = 11;
    if(flags == EVEN && ((num % 2) == 1)
        num++;
    else if(flags == ODD && ((num % 2) == 0)
        num++;
    return num;
}
//called like this
int Number = CreateNum(GREATER_THAN_TEN | EVEN);

これは可能ですか?

4

6 に答える 6

32

「単一ビット」値を指定する列挙型を定義できます (ここでは、囲んでいる構造体がネーミング コンテキストとしてのみ機能することに注意してください。たとえば、次のように記述できますMyFlags::EVEN)。

struct MyFlags{
    enum Value{
        EVEN                           = 0x01,
        ODD                            = 0x02,
        ANOTHER_FLAG                   = 0x04,
        YET_ANOTHER_FLAG               = 0x08,
        SOMETHING_ELSE                 = 0x10,
        SOMETHING_COMPLETELY_DIFFERENT = 0x20
    };
};

そして、次のように使用します。

int CreateNum(MyFlags::Value flags){
    if (flags & MyFlags::EVEN){
        // do something...
    }
}

void main(){
    CreateNum((MyFlags::Value)(MyFlags::EVEN | MyFlags::ODD));
}

または単に次のように:

int CreateNum(int flags){
    if (flags & MyFlags::EVEN){
        // do something...
    }
}

void main(){
    CreateNum(MyFlags::EVEN | MyFlags::ODD);
}

単純に整数定数を宣言することもできますが、私の意見では列挙型の方が明確です。

注:いくつかのコメントを考慮して投稿を更新しました、ありがとう!

于 2009-10-19T15:11:06.580 に答える
13

私は orsogufo の答えに賛成票を投じましたが、値を定義するために次のことをするのが好きでした:

enum Value{
  EVEN                           = (1<<0),
  ODD                            = (1<<2),        
  ANOTHER_FLAG                   = (1<<3),        
  YET_ANOTHER_FLAG               = (1<<4),        
  SOMETHING_ELSE                 = (1<<5),        
  SOMETHING_COMPLETELY_DIFFERENT = (1<<6),

  ANOTHER_EVEN                   = EVEN|ANOTHER_FLAG
};

<< はシフト演算子です。右側をインクリメントすると、一度に 1 ビットずつ 1 を移動することで、連続したビット マスクを生成できます。これは裸のフラグと同じ値を持っていますが、私の目には読みやすく、値をスキップまたは複製した場合に明らかになります。

また、必要に応じて、いくつかの一般的なフラグの組み合わせを組み合わせるのも好きです。

于 2009-10-19T15:43:20.857 に答える
6

const int次のように使用できます。

const int FLAG1 = 0x0001;
const int FLAG2 = 0x0010;
const int FLAG3 = 0x0100;
// ...

そして、あなたがそれを使うとき:

int CreateNum(int flags)
{
    if( flags & FLAG1 )
        // FLAG1 is present

    if( flags & FLAG2 )
        // FLAG2 is present

    // ...
}

もちろん、|演算子を使用してフラグに 1 つ以上のフラグを入れることができます。

于 2009-10-19T15:12:58.883 に答える
1

次のように、個々の定数として 2 の累乗を使用します。

enum Flags { EVEN = 0x1, ODD = 0x2, GREATER_TEN = 0x4 };

そして、次のように、論理 AND 演算子 '&' をテストに使用します。

if( flags & GREATER_THAN_TEN)
    num = 11;
if( (flags & EVEN) && (num % 2) == 1 )
    num++;
else if ( (flags & ODD) && (num % 2) == 0 )
    num++;
return num;
于 2009-10-19T15:16:29.537 に答える
0
enum flags {
    EVEN =        0x0100,
    ODD =         0x0200,
    BELOW_TEN =   0x0400,
    ABOVETEN =    0x0800,
    HUNDRED =     0x1000,
    MASK =        0xff00
};

void some_func(int id_and_flags)
{
    int the_id = id_and_flags & ~MASK;
    int flags = id_and_flags & MASK;
    if ((flags & EVEN) && (the_id % 2) == 1)
        ++the_id;
    if ((flags & ODD) && (the_id % 2) == 0)
        ++the_id;
    // etc
}

ビットフィールドのマスキングについても説明します。これは、データ構造を追加せずに、単純なビットの追加機能を追加する必要がある場合に役立ちます。

于 2009-10-19T15:33:22.103 に答える
0

テストが間違っています。あなたが望むのは(flags & EVEN)、EVENが単一のビットセットを持つ整数(1、2、4、8、16 - 2の累乗)のようなものです。(整数は int または enum にすることができます。マクロを使用することもできますが、一般的にはお勧めできません。)

をオーバーロードすることで、リストした表記を使用できますflags::operator==(flagvalue f)が、それは悪い考えです。

于 2009-10-19T15:13:53.147 に答える