令人惊讶的是,我无法通过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
,我想是吗?
我理解范围是由{}
块定义的,但这似乎是一个合理的例子,嗯,异常。是否抛出异常导致对象无法完全构造?
答案 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)
它们超出了范围。这是因为如果你声明一个对象并尝试启动它,并且你启动它的方式会抛出异常,它就会被捕获。