在异常处理程序中使用'goto'的样式不好?

时间:2014-04-23 13:57:11

标签: c++ exception exception-handling goto

自从我开始编程以来,我被教导如果可以避免,就不要使用'goto'。然而,我遇到了一个案例,我认为goto是保持此代码清洁的最简单方法。

我的代码如下例所示:

// code within a for-loop
// ...
// ...
try{
      if(!ifstream.open())
          throw special_exception;

      A_EXCEPTION_HANDLED:
//...
//...
}
catch(special_exception ex)
{
  // trying to fix the error here
  if(error_is_fixed)
     goto A_EXCEPTION_HANDLED;

  // else clean up and show error message
};

此示例位于嵌套循环内部,我需要确保throw之后的代码正确执行,因此我必须编写大量开销来启动迭代,再次抛出异常。 这种情况会被认为是对goto的合理使用,还是像跳出循环等那样糟糕的风格?

5 个答案:

答案 0 :(得分:2)

我认为根据您的描述,代码可以像这样重写:

for ( /* usual stuff */ )
    try{
          if(!ifstream.open())
              throw special_exception;
    } catch (const special_exception&) {
        if (/* "can't handle the truth!" */) {
            // clean up & show error message
            break;
        }
    }
    // OK, continue
}

答案 1 :(得分:2)

在异常之后重试的概念并非闻所未闻(例如:Common Lisp实现了类似语言的一部分)。

但是,你真的需要例外吗?如果你(而不是库)抛出异常,并且只有一个地方被抛出(如你的例子所示),难道你不能简单地写这样的东西吗?

if(!ifstream.open()) {
    // trying to fix the error here
    if(!error_is_fixed) {
        throw really_unrecoverable();
    }
    // else let it continue normally
}

如果这个逻辑经常重复,我可以看到异常的理由并用goto重试算法。但是,如果它只发生一次或两次,我会编写恢复内联的代码(可能有辅助函数)。

答案 2 :(得分:0)

使用goto实现循环不能合理使用goto

要在C ++中实现循环,请使用循环结构。

关于具体案例的详细信息,请提供。

答案 3 :(得分:0)

在你给出的例子中,我认为使用goto遍历两个块确实是不好的风格。

现在使用'goto'会产生各种不受欢迎的歇斯底里,但在这种情况下,它的风格很糟糕的原因很明显:

您的代码的读者可能会合理地期望一旦调用了异常处理程序,就会发生一些非常糟糕的事情,阻止当前的代码上下文继续。 如果预期ifstream存在而不存在,则这是一种例外情况,并且保证例外。 但是,如果打开流的尝试只是一个可以合理预期会失败的测试,那么这不是一件特别的事情。在这种情况下,根本不要使用例外。 在这种情况下,表达意图的更好方式可能是这样的:

for(/* usual stuff */)
    while (!ifstream.open()) {
      if (!attemptRemedialAction()) {
        throw really_bad_thing_happened_exception;
      }
    }
  // do things with ifstream, 
  // including goto statements if they express your intent elegantly
}

// allow the outer context or the caller to deal with the exceptional case of non-recovery

答案 4 :(得分:0)

风格正是它听起来的样子。有些人喜欢一个,有些人喜欢另一个。作为开发人员,您将与许多人合作,并且必须处理他们的不同风格。

非常重要的是不要将一种风格传播到另一种风格,而是要在项目中保持风格的一致性。如果此项目使用goto,则坚持使用,并相应地编写您的部件。因为其他开发人员会期待跳跃并且会寻找它们。

(作为旁注,有些系统在任何给定时间都只允许存在一个例外,例如Symbian和其他EPOC衍生产品,因此我们在这里看到的可能是必需品而非风格)