更好地结构部分重叠的案例陈述

时间:2015-08-24 17:19:03

标签: c switch-statement

说出那个做了动作A,B,C,D的案例1和做出E,B,C,D的案例2.是否有更好的方法来构建这个,而不是下面的内容?

switch (id)
{
    case 1:
    case 2:
        if (id==1) A();
        if (id==2) E();
        B();
        C();
        D();
        break;
    //More cases below
}

或者

switch (id)
{
    case 1:
        A();
        B();
        C();
        D();
        break;
    case 2:
        E();
        B();
        C();
        D();
        break;
    //More cases below
}

澄清:所以我想根据我拥有的对象类型分解要完成的操作。所有这些对象都不会共享除了这两个行为之外的所有行为,除了每个行为都是独一无二的行为之外的所有行动。

6 个答案:

答案 0 :(得分:4)

就个人而言,我可能会使用辅助函数,并期望编译器适当地内联。假设三个共享动作形成一个有用的结合似乎是合理的,因为它被多次调用。

void BCD(void) {
  B();
  C();
  D();
}
// ...
switch (id) {
  case 1: A(); BCD(); break;
  case 2: E(); BCD(); break;
  // ...
}

有些人(不是我)可能会说这是对goto的合法使用,使用相同的参数但不相信编译器优化:

switch (id) {
  case 1: A();
          goto BCD;
  case 2: E();
     BCD: B();
          C();
          D();
          break;
  //...
}

作为一种历史好奇心,它是 legal ,但强烈反建议使用不正确的嵌套条件来影响goto。请参见示例live on ideone.

答案 1 :(得分:0)

switch构造的使用完全取决于需要。

此处代替switch if else if看起来更合适。 在您显示的第一个示例中switch没有任何意义,因为您要经过if检查,而不管id传递给switch的情况如何执行的陈述是一样的。

if(id == 1)
{
  A();
}
else if(id == 2)
{
  B();
}
else if()
{
......
/* Rest of your conditions */
}
else
{

}

答案 2 :(得分:0)

如果没有完整的问题说明,很难知道什么是最好的。这里有一个替代方案,可以利用switch case-fall-through来处理问题中的琐碎要求

// handle the two oddball objects
switch (id)
{
    case 1:   A();   break;
    case 2:   E();   break;
}

// handle all the objects
switch (id)
{
    case 1:
    case 2:
        B();
        C();
        D();
        break;
    // other cases
}

答案 3 :(得分:0)

对于给出的星座,我使用:

switch (id)
{
    case 1:
        A();
        // add a comment why you do not break here!
    case 2:
        if ( id == 2 )   // the compiler might optimize this
            E();
        B();
        C();
        D();
        break;
    //More cases below
}

智能编译器可能会检测到if并将其转换为跳过E();

但实际的分组完全取决于整个序列。例如。函数参数可能会改变最佳解决方案。

答案 4 :(得分:0)

(1)也许,你可以将它们放在一个函数指针表中。

void (*func[3])() = {0 /*dummy*/, A, B }; 

....

switch (id)
{
    case 1:
    case 2:
        func[id]();
        B();
        C();
        D();
        break;
}

(2),也可以包装其他功能:

void BCD(void){
        B();
        C();
        D();
}

void (*func[3])() = {0 /*dummy*/, A, B }; 

....

switch (id)
{
    case 1:
    case 2:
        func[id]();
        BCD();
        break;
}

这"包装"这里没问题,但如果这些函数碰巧返回错误/值,通常可能不合适。

(3)您也可以将func[id]();移至包装器并将id传递给BCD()

void (*func[3])() = {0 /*dummy*/, A, B }; 

void func_calls(int id){
        func[id]();
        B();
        C();
        D();
}

...

switch (id)
{
    case 1:
    case 2:
        func_calls(id);
        break;
}

以上是否有任何更好的"取决于你对更好的定义:)

答案 5 :(得分:0)

以这种方式保留概述,以防您有更多这样的条件:

switch (id) 
{
  case 1:
  case 2:

    switch(id)
    {
      case 1:
        A();
        break;

      case 2:
        E();
        break;

      default:
        assert(0);
        break;
    }

    B();
    C();
    D();

    break;

  //More cases below

  default:
    assert(0);
    break;
}

优化由编译器完成。