9

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

myFunction(One | Two);

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

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

现在,如果我尝试使用 One | 调用该函数 二,我希望两个开关盒都被调用。我不太擅长二元运算符,所以我真的不知道该怎么做。任何想法都会很棒!

谢谢!

4

5 回答 5

14

为此,您必须制作如下枚举:

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

即枚举元素值应该是 2 的幂来选择有效的 case 或 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);
}
于 2009-12-09T14:01:46.283 回答
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)

因此,您没有给出两个选项,而是给出了六个。

于 2009-12-09T14:21:08.133 回答
3

通常以这种方式组合的参数是十进制值为 1、2、4、8 等的标志(设置单个位的值)。假设 One 和 Two 遵循此规则,则不能使用开关检查两个都。交换机只遵循一条路径。您的组合参数不等于一或二,而是它们的组合(1 | 2 == 3)。您可以检查是否设置了 One 或 Two ,如下所示:

if (_a & One)
{

}
if (_a & Two)
{

}

请记住,没有显式值的标准枚举只会向上计数,而不是使用下一位。如果您定义的下一个值是三,它可能等于 3,这不是单个位的值,然后会表现得好像您已将两个标志(一 | 二)传递给函数。您需要自己设置枚举的值。

于 2009-12-09T13:59:28.940 回答
2

您必须拆分可能的“令牌”(当然不重叠......使用 2 的幂):

if (_a & One) { ... }

不优雅真的用 1 个 switch 语句做你想做的事:使用if语句拆分。

于 2009-12-09T13:55:17.620 回答
2

你最好用一组 if 语句来做......

IE

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 个选项相对健全,但一旦你获得更多选项,它就会开始失控。如果您有 32 个选项,那么您将有一个不太可能适合任何机器的 switch 语句。“如果”解决方案中的所有内容都更清洁,更理智:)

于 2009-12-09T13:55:47.230 回答