我只是问一个一般性的问题,当我在处理其中一个库项目时出于好奇而在另一个方法中抛出异常而不是返回值,但我想将该异常转换为返回值。我使用多个 try catch 块解决了它,但只是想知道 C++ 中是否有办法在抛出异常后恢复。
3 回答
我不完全确定你想要什么。将异常转换为返回码并不是在异常发生后恢复。C++ 委员会考虑恢复,但不清楚这可能意味着什么。考虑:
int
someFunction()
{
// ...
if ( someCondition ) {
throw SomeException();
}
assert( !someCondition );
// ...
}
在 C++ 中,assert
永远不会触发(并且通常不会编写它,因为if
和throw
清楚地表明断言的条件在之后有效)。如果您可以恢复异常,assert
则将(或至少可能)触发;您将失去代码验证的重要手段。
也曾在其他语言中使用过它的人报告说它实际上并不能很好地工作,并且在他们开始使用恢复的每种情况下,他们都不得不更改代码以便以后不再使用它。
不会。事实上,在抛出异常后,编译器甚至可能不会为无法访问的代码发出指令:
throw std::invalid_argument;
int i = 5; // No instructions generated for this, as it is unreachable.
为了让resume
指令安全工作,它不仅应该在 之后跳转,而且应该在它throw
之前的if
之前跳转,以便重新测试条件。
这里的问题是,顺便说一下,C++ 异常被认为是语句本身,不一定是直接条件分支。(if
并且throw
相互独立定义)
此外,在 thethrow
和 the catch
(可能是外部的几个函数调用)之间有一个名为“ stack unrolling”的东西,它实际上调用了所有本地内容的所有析构函数,这些析构函数留在了必须转义的块中。一个“ resume
”应该重构所有这些对象,但是由于这些析构函数的动作不依赖于 throw 指令本身,并且可能不是“可逆的”,因此几乎不可能一致地恢复系统状态。
一个可能的成语可以是
for(;;)
{
try
{
... everything may throw ...
break; //if you are here everything was successful, so stop looping and go on
}
catch(whatever_you_may)
{
try_to_repair;
if(impossible) throw;
}
}
实际上,您循环直到成功或决定不再是这种情况。
但请注意这是重新执行,而不是重新构建(或不破坏)