所以我在这个链接中读到了函数try块。有一行描述了正常试块和像这样的功能试块之间的区别
与普通捕获块不同,普通捕获块允许您解决异常、抛出新异常或重新抛出现有异常,对于函数级尝试块,您必须抛出或重新抛出异常
但是我试着写一个像这样的函数try块
#include <iostream>
int add(int a, int b) try {
throw 1;
return a + b;
}
catch (int) {
std::cout << "catch in add()";
}
int main()
{
try {
add(1, 2);
}
catch (int) {
std::cout << "catch in main()";
}
}
输出为
catch in add()
如果函数try块不允许我们解决异常,那么为什么catch in main()
没有打印
有一行描述了正常try块和函数try块之间的区别,比如
那一行不准确。常规函数的函数try块的行为就好像它们只是函数的唯一内容一样。也就是说,你对add
的定义与完全相同
int add(int a, int b) {
try {
throw 1;
return a + b;
}
catch (int) {
std::cout << "catch in add()";
}
}
差异出现在构造函数中。首先,函数级try块是捕获初始化类成员时引发的异常的唯一方法。
其次,一旦从成员的初始化中抛出异常,构造函数就无法完成,因此对象就不会初始化。正是在这里,我们不能简单地接受这个例外。如果初始化因引发异常而失败,则必须将该异常传播或转换为其他类型并重新引发。
你链接的页面上的例子总结了代码
B(int x) try : A(x) // note addition of try keyword here
{
}
catch (...) // note this is at same level of indentation as the function itself
{
// Exceptions from member initializer list or constructor body are caught here
std::cerr << "Exception caughtn";
// If an exception isn't explicitly thrown here, the current exception will be implicitly rethrown
}
函数try-block是否允许我们解决异常?
是。
强制的自动抛出只适用于少数情况,如构造函数和析构函数。示例函数既不是构造函数,也不是析构函数。
附言:该示例的行为是未定义的,因为它未能从非void函数返回值。
下面的教程有一部分是错误的。上面写着:
最后,与允许您解析异常、抛出新异常或重新抛出现有异常的普通catch块不同,对于函数级try块,您必须抛出或重新抛出异常。如果没有显式抛出新异常,或重新抛出当前异常(单独使用throw关键字(,则该异常将在堆栈中隐式重新抛出。
这对于函数来说是完全不正确的。
然而,对于构造函数和析构函数,这是真的
13如果返回语句出现在构造函数的函数try-block的处理程序中,则程序格式错误。
14如果控件到达构造函数或析构函数的try块的处理程序的末尾,则当前处理的异常将被重新抛出否则,从函数try块的处理程序的复合语句末尾流出相当于从该函数的复合语句结尾流出。
--N4713[除.handle](强调矿(
第14点的第一句话证实了构造函数和析构函数的这种行为。第二句话与你正在学习的教程中的信息直接矛盾,因为它们没有区分这两种情况。
请注意,您的代码会导致未定义的行为,因为函数的catch块不会抛出异常,也不会返回值,并且函数不会返回void。您必须从catch块返回一个值以避免UB。