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

您可以定义一个指定“一位”值的枚举(请注意,封闭结构在此处仅用作命名上下文,因此您可以编写 eg 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 来生成顺序位掩码,一次一位。这对于裸标志具有相同的值,但在我看来更容易阅读,并且如果您跳过或复制一个值,它就会很明显。

我也喜欢在适当的时候组合一些常见的标志组合。

于 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

    // ...
}

当然,您可以使用|运算符在标志中放置一个或多个标志。

于 2009-10-19T15:12:58.883 回答
1

使用 2 的幂作为单个常数,例如

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

并且您使用逻辑和运算符“&”进行测试,例如

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

你的测试错了。你想要的是这样的(flags & EVEN),其中 EVEN 是一个具有单个位集的整数(1、2、4、8、16 - 2 的某个幂)。(整数可以是 int 或 enum。你可以有一个宏,但这通常不是一个好主意。)

您可以通过重载使用您列出的符号flags::operator==(flagvalue f),但这是一个坏主意。

于 2009-10-19T15:13:53.147 回答
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 回答