在C++中,如何在一个函数参数中使用多个枚举类型?可以使用按位或“|”操作符。

10

我最近遇到一些可以传递多个枚举值的函数,像这样:

myFunction(One | Two);

我认为这是一种非常优雅的方式,因此我尝试自己实现类似的东西:

void myFunction(int _a){
    switch(_a){
        case One:
            cout<<"!!!!"<<endl;
            break;
        case Two:
            cout<<"?????"<<endl;
            break;
    }
}

现在,如果我尝试使用 One | Two 调用该函数,我希望两个switch语句都被调用。我不太擅长二进制运算符,所以不知道该怎么做。有什么想法吗?

谢谢!


1
发布你的enum定义...你记得把它们都设为2的幂次方了吗? - eduffy
1
请注意,名称_a保留用于C ++实现,除非它是类成员的名称。 - anon
5个回答

17

为此,您需要创建枚举类型,例如:

enum STATE {
  STATE_A = 1,
  STATE_B = 2,
  STATE_C = 4
};

也就是说,枚举元素的值应该是2的幂,这样才能选择有效的情况或if语句。

因此,当您执行以下操作时:

void foo( int state) {

  if ( state & STATE_A ) {
    //  do something 
  }

  if ( state & STATE_B ) {
    //  do something 
  }

  if ( state & STATE_C ) {
    //  do something 
  }   
}

int main() {
  foo( STATE_A | STATE_B | STATE_C);
}

12
更好的方式是使用 enum STATE { STATE_A = 1 << 0, STATE_B = 1 << 1, STATE_C = 1 << 2 }; - 我认为这样更加明确。 - DevSolar
3
顺便提一下,它们不会成为“州”。因为州的本意是排他性的。它们更可能是旗帜(其中各个旗帜彼此独立)。 - paxdiablo

9

按位运算符仅针对2的幂次方有效:

  0010
| 0100
------
  0110  // both bits are set


  0110
& 0100
------
  0100  // nonzero, i.e. true: the flag is set

如果您尝试使用任意数字进行相同操作,将会得到意想不到的结果:

  0101  // 5
| 1100  // 12
------
  1101  // 13

这个标志位包含以下可能的(任意)数字:0001(1)、0100(4)、0101(5)、1000(8)、1001(9)、1100(12)、1101(13)。

因此,您不再只提供两个选项,而是提供了六个选项。


3
通常,以这种方式组合的参数都是标志(只设置一个位的值),其十进制值为1、2、4、8等。假设One和Two遵循此规则,您不能使用switch检查两者。开关只遵循一条路径。您的组合参数不等于One或Two,而是它们的组合(1 | 2 == 3)。您可以像这样检查One或Two是否已设置:
if (_a & One)
{

}
if (_a & Two)
{

}

请记住,如果没有显示指定值的标准枚举将只会逐个计数,而不使用下一个位。 如果您定义的下一个值是Three,则它很可能等于3,这不是单个位的值,然后它将像您已向函数传递了两个标志(One | Two)一样运行。 您需要自己设置枚举的值。


2

使用一组if语句会更好...

例如:

if ( _a & ONE )
{
   // Do stuff.
}
if ( _a & TWO )
{
  // Do other stuff.
}

编辑:你也可以使用 switch 语句来实现,但这将是一场噩梦。你需要像这样的东西。
switch( _a )
{
case ONE:
   // Handle ONE.
   break;

case TWO:
   // Handle TWO.
   break;

case ONE | TWO:
   // Handle ONE.
   // Handle TWO.
   break;
};

如果只有2个选项,使用开关语句还相对合理。但是,一旦选项变得超过2个,代码就开始失控了。如果你有32个选项,开关语句很可能无法适应任何计算机。所以,用"if"语句的解决方案更加简洁和明智 :)


谢谢,你说得对,我现在使用if语句,它的效果非常好! - moka

2

您需要将可能的“令牌”(当然是非重叠的...要使用2的幂)分割:

if (_a & One) { ... }

如果你只用一个switch语句,代码就不会显得优雅。可以使用if语句进行拆分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接