为什么不捕获块共享try块的范围?

时间:2011-03-29 17:25:32

标签: c++ exception-handling error-handling try-catch

令人惊讶的是,我无法通过Google搜索和搜索来找到答案(在SO上有很多类似的问题,但与其他语言有关)。

我怀疑答案是no。如果是这样,会有明显的不便,例如

try
{
  std::string fname = constructFileName(); // can throw MyException
  ofstream f;
  f.exceptions(ofstream::failbit | ofstream::badbit);
  f.open(fname.c_str());
  // ...
}
catch (ofstream::failure &e)
{
  cout << "opening file " << fname << " failed\n"; // fname is not in the scope
}
catch (MyException &e)
{
  cout << "constructing file name failed\n";
}

如果我的假设是正确的,你如何处理?将std::string fname;移出try,我想是吗?

我理解范围是由{}块定义的,但这似乎是一个合理的例子,嗯,异常。是否抛出异常导致对象无法完全构造?

4 个答案:

答案 0 :(得分:19)

  

catch块是否共享try块的范围?

没有

  

你是如何处理的?将std::string fname;移出try,我想是吗?

  

我理解范围是由{}块定义的,但这似乎是一个合理的例子,嗯,异常。是否抛出异常导致对象无法完全构造?

C ++需要的最后一件事是规则更复杂的规则和例外。 : - )

答案 1 :(得分:5)

有一个明显的原因:你不能相信在try块中创建的对象的状态。那里的代码被异常打断了,他们的构造函数可能还没有运行。

答案 2 :(得分:3)

虽然詹姆斯的帖子正确回答了你的问题,但它并没有提供通常的解决方法:swap。假设constructFileName()返回std::string而非char const*,则以下是惯用的:

std::string fname;
try
{
    constructFileName().swap(fname); // can throw MyException
    std::ofstream f;
    f.exceptions(std::ios_base::failbit | std::ios_base::badbit);
    f.open(fname.c_str());
    // ...
}
catch (std::ios_base::failure &e)
{
    std::cout << "opening file " << fname << " failed\n";
}
catch (MyException &e)
{
    std::cout << "constructing file name failed\n";
}

答案 3 :(得分:0)

它们超出了范围。这是因为如果你声明一个对象并尝试启动它,并且你启动它的方式会抛出异常,它就会被捕获。