catch 块共享 try 块的作用域吗?

问题描述 投票:0回答:4

令人惊讶的是,我无法通过谷歌搜索和搜索SO找到答案(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
来实现的?

我知道范围是由

{}
块定义的,但这似乎是一个合理的情况,嗯,例外。是不是抛出异常就无法完整构造对象的原因?

c++ exception error-handling try-catch
4个回答
25
投票

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

没有。

你如何处理这个问题? 我猜是通过将

std::string fname;
移出
try
来实现的?

是的。

我知道范围是由

{}
块定义的,但这似乎是一个合理的情况,嗯,例外。是不是抛出异常就无法完整构造对象的原因?

C++ 最不需要的就是更复杂的规则和规则的例外。 :-)


12
投票

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


4
投票

虽然 James 的帖子正确回答了您的问题,但它没有提供通常的解决方法:

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";
}

1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.