C++ 如果抛出异常并且该异常与捕获的异常类型不匹配,try-catch 语句的行为是什么?
C++ What is the behavior of a try-catch statement if an exception is thrown, and that exception does not match the type of exception caught?
我有兴趣进一步了解以下代码逻辑的行为方式:
try
{
// might, or might not do this: throw ExceptionTypeA;
function_which_might_throw_exception_type_a();
do_A(); // do we do A?
}
catch(ExceptionTypeB)
{
// B will never be done
do_not_do_B();
}
// C is always done (Edit: should always be done, but actually isn't)
do_C();
简而言之,这个问题可以简单表述为:函数do_A
会被调用吗?*
*[如果function_which_might_throw_exception_type_a()
做throw ExceptionTypeA;
...当然很清楚do_A()
会如果function_which_might_throw_exception_type_a()
不会抛出异常。]
上面的伪代码应该表示抛出的异常类型与 catch
子句中捕获的异常类型不同。
换句话说,虽然有一个catch
子句,但这里不会捕获异常,因为它不是正确的类型。
在这种情况下,编译器生成的输出是 完全跳过 do_A()
的调用, 还是编译器生成的输出中 do_A()
被称为`?
我相当有信心,如果在try块中抛出任何异常,那么执行路径就是立即离开try块。 也就是说,我认为上面的伪代码中并没有调用do_A()
。 (假设函数 function_which_might_throw_exception_type_a()
确实抛出 ExceptionTypeA
。)
但是我想检查一下,因为我开始怀疑了。
仅供参考:我正在查看一段代码,更明智的做法是:
try
{
// might, or might not do this: throw ExceptionTypeA;
function_which_might_throw_exception_type_a();
do_A(); // do we do A?
// C **should** always be done
do_C()
}
catch(ExceptionTypeB)
{
// B will never be done
do_not_do_B();
}
return something;
但是,我认为这不等同于第一个伪代码。
由于C++没有try-catch-finally类型的语句,所以不能这样表达逻辑。 (但我觉得如果可以的话会更好。)
Will the function do_A be called?
简而言之——没有。当在 try
块内抛出异常时,该块将 立即 退出。如果抛出的异常类型没有被相应的 catch
块处理,那么它将被视为在 try
块之外抛出的异常(可能 导致堆栈展开,但最终导致程序终止)。
如果您希望 do_C()
函数被调用 'always',无论抛出什么类型的异常,您都应该添加一个 catch(...)
(称为“catch-all 子句”)块在你的其他特定 catch
块之后。这可以是一个空 statement/block;如果是这样,抛出的异常仍会被捕获(即不会进一步传播)但不会采取任何具体操作。
实现您想要的东西的可能方法如下:
try
{
// might, or might not do this: throw ExceptionTypeA;
function_which_might_throw_exception_type_a();
do_A(); // If the above throws, this WILL NOT be executed
}
catch(ExceptionTypeB)
{
// B will never be done
do_not_do_B();
}
catch(...) {} // This will catch "ExceptionTypeA" but do nothing about it ...
do_C(); // Will 'always' execute (unless an earlier catch re-throws)
return something;
我有兴趣进一步了解以下代码逻辑的行为方式:
try
{
// might, or might not do this: throw ExceptionTypeA;
function_which_might_throw_exception_type_a();
do_A(); // do we do A?
}
catch(ExceptionTypeB)
{
// B will never be done
do_not_do_B();
}
// C is always done (Edit: should always be done, but actually isn't)
do_C();
简而言之,这个问题可以简单表述为:函数do_A
会被调用吗?*
*[如果function_which_might_throw_exception_type_a()
做throw ExceptionTypeA;
...当然很清楚do_A()
会如果function_which_might_throw_exception_type_a()
不会抛出异常。]
上面的伪代码应该表示抛出的异常类型与 catch
子句中捕获的异常类型不同。
换句话说,虽然有一个catch
子句,但这里不会捕获异常,因为它不是正确的类型。
在这种情况下,编译器生成的输出是 完全跳过 do_A()
的调用, 还是编译器生成的输出中 do_A()
被称为`?
我相当有信心,如果在try块中抛出任何异常,那么执行路径就是立即离开try块。 也就是说,我认为上面的伪代码中并没有调用do_A()
。 (假设函数 function_which_might_throw_exception_type_a()
确实抛出 ExceptionTypeA
。)
但是我想检查一下,因为我开始怀疑了。
仅供参考:我正在查看一段代码,更明智的做法是:
try
{
// might, or might not do this: throw ExceptionTypeA;
function_which_might_throw_exception_type_a();
do_A(); // do we do A?
// C **should** always be done
do_C()
}
catch(ExceptionTypeB)
{
// B will never be done
do_not_do_B();
}
return something;
但是,我认为这不等同于第一个伪代码。
由于C++没有try-catch-finally类型的语句,所以不能这样表达逻辑。 (但我觉得如果可以的话会更好。)
Will the function do_A be called?
简而言之——没有。当在 try
块内抛出异常时,该块将 立即 退出。如果抛出的异常类型没有被相应的 catch
块处理,那么它将被视为在 try
块之外抛出的异常(可能 导致堆栈展开,但最终导致程序终止)。
如果您希望 do_C()
函数被调用 'always',无论抛出什么类型的异常,您都应该添加一个 catch(...)
(称为“catch-all 子句”)块在你的其他特定 catch
块之后。这可以是一个空 statement/block;如果是这样,抛出的异常仍会被捕获(即不会进一步传播)但不会采取任何具体操作。
实现您想要的东西的可能方法如下:
try
{
// might, or might not do this: throw ExceptionTypeA;
function_which_might_throw_exception_type_a();
do_A(); // If the above throws, this WILL NOT be executed
}
catch(ExceptionTypeB)
{
// B will never be done
do_not_do_B();
}
catch(...) {} // This will catch "ExceptionTypeA" but do nothing about it ...
do_C(); // Will 'always' execute (unless an earlier catch re-throws)
return something;