C++ 嵌套的 try-catch 捕获相同的异常 - 我应该如何重写这段代码?
C++ nested try-catch catching the same exceptions - how should I rewrite this code?
我目前的 C++ 14 代码如下所示:
try {
// create objects, process input
myObject obj; // may throw std::invalid_argument in constructor
for (i = 0; i < n_files; i++)
{
try {
process_file(); // may throw std::invalid_argument and std::runtime_error()
}
catch (std::exception& e)
{// print error
continue;
}
}
catch (std::exception& e)
{// print error
return 0;
}
对于我自己的函数,我只是抛出像 std::runtime_error 和 std__invalid_exception 这样的标准异常。
想法是,在外部 try 块中创建的对象应该抛出异常并被外部 catch 块捕获,然后结束程序。 process_file() 抛出的异常将被内部 try 块捕获,它只会打印一些错误但不会导致程序终止,程序将继续处理下一个文件。
外部 try 块包含随后将在内部 try-catch 中使用的对象构造函数调用,因此我不能简单地将它移动到它自己的 try-catch 中,否则循环中的对象将是未定义的。
但是根据我的理解,这段代码是行不通的,因为在外部 try 块中抛出的异常会首先命中内部 catch 语句,因为这是代码中可到达的第一个 catch 语句。此外,像这样嵌套的 try-catch 会很糟糕 form/confusing 从我读过的内容中读取。
这样做的正确方法是什么?
谢谢!
this code as is won't work from what I understand
是的,对于您所描述的情况,它会工作得很好。
exceptions thrown in the outer try block would hit the inner catch statement first, as that is the first catch statement reachable in the code.
这是不正确的。这与代码中的顺序无关,而是范围内的顺序。如果外部 try
抛出,则内部 try
不在范围内。异常沿着调用堆栈上升,从当前作用域开始,然后是最近的外部作用域,然后是下一个外部作用域,依此类推,直到找到匹配的 catch
。例如:
try {
// if any std exception is thrown here, jumps to A below...
try {
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
for (int i = 0; i < n_files; ++i)
{
try {
// if any std exception is thrown here, jumps to C below...
}
catch (std::exception& e) // C
{
// print error
continue;
}
}
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
}
catch (invalid_argument& e) // B
{
// print error
return 0;
}
}
catch (exception& e) // A
{
// print error
return 0;
}
nested try-catch like this would be bad form/confusing to read from what I've read.
这也不正确。使用嵌套 try
块没有错。
但是,在此示例中,让内部 try
捕获 ONLY std::invalid_argument
和 std::runtime_error
更有意义,因为这些是它期望并愿意忽略以继续循环的 2 种类型。一般不要在那个地方抓std::exception
。这样,如果 process_file()
抛出一些 unexpected(例如 std::bad_alloc
),那么外部 catch
应该处理它以终止进程。
try {
// if any std exception is thrown here, jumps to A below...
try {
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
for (int i = 0; i < n_files; ++i)
{
try {
// if std::invalid_argument is thrown here, jumps to D below...
// if std::runtime_error is thrown here, jumps to C below...
// if any other std exception is thrown here, jumps to A below...
}
catch (std::invalid_argument& e) // D
{
// print error
continue;
}
catch (std::runtime_error& e) // C
{
// print error
continue;
}
}
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
}
catch (invalid_argument& e) // B
{
// print error
return 0;
}
}
catch (exception& e) // A
{
// print error
return 0;
}
设计 catch
的最佳方法是让它只捕获它知道如何在代码中的那个位置处理的 特定 类型的异常。让外部 catch
处理其他所有事情。如果抛出异常并且没有找到匹配的catch
来处理它,进程将默认终止。
我目前的 C++ 14 代码如下所示:
try {
// create objects, process input
myObject obj; // may throw std::invalid_argument in constructor
for (i = 0; i < n_files; i++)
{
try {
process_file(); // may throw std::invalid_argument and std::runtime_error()
}
catch (std::exception& e)
{// print error
continue;
}
}
catch (std::exception& e)
{// print error
return 0;
}
对于我自己的函数,我只是抛出像 std::runtime_error 和 std__invalid_exception 这样的标准异常。
想法是,在外部 try 块中创建的对象应该抛出异常并被外部 catch 块捕获,然后结束程序。 process_file() 抛出的异常将被内部 try 块捕获,它只会打印一些错误但不会导致程序终止,程序将继续处理下一个文件。
外部 try 块包含随后将在内部 try-catch 中使用的对象构造函数调用,因此我不能简单地将它移动到它自己的 try-catch 中,否则循环中的对象将是未定义的。
但是根据我的理解,这段代码是行不通的,因为在外部 try 块中抛出的异常会首先命中内部 catch 语句,因为这是代码中可到达的第一个 catch 语句。此外,像这样嵌套的 try-catch 会很糟糕 form/confusing 从我读过的内容中读取。
这样做的正确方法是什么? 谢谢!
this code as is won't work from what I understand
是的,对于您所描述的情况,它会工作得很好。
exceptions thrown in the outer try block would hit the inner catch statement first, as that is the first catch statement reachable in the code.
这是不正确的。这与代码中的顺序无关,而是范围内的顺序。如果外部 try
抛出,则内部 try
不在范围内。异常沿着调用堆栈上升,从当前作用域开始,然后是最近的外部作用域,然后是下一个外部作用域,依此类推,直到找到匹配的 catch
。例如:
try {
// if any std exception is thrown here, jumps to A below...
try {
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
for (int i = 0; i < n_files; ++i)
{
try {
// if any std exception is thrown here, jumps to C below...
}
catch (std::exception& e) // C
{
// print error
continue;
}
}
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
}
catch (invalid_argument& e) // B
{
// print error
return 0;
}
}
catch (exception& e) // A
{
// print error
return 0;
}
nested try-catch like this would be bad form/confusing to read from what I've read.
这也不正确。使用嵌套 try
块没有错。
但是,在此示例中,让内部 try
捕获 ONLY std::invalid_argument
和 std::runtime_error
更有意义,因为这些是它期望并愿意忽略以继续循环的 2 种类型。一般不要在那个地方抓std::exception
。这样,如果 process_file()
抛出一些 unexpected(例如 std::bad_alloc
),那么外部 catch
应该处理它以终止进程。
try {
// if any std exception is thrown here, jumps to A below...
try {
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
for (int i = 0; i < n_files; ++i)
{
try {
// if std::invalid_argument is thrown here, jumps to D below...
// if std::runtime_error is thrown here, jumps to C below...
// if any other std exception is thrown here, jumps to A below...
}
catch (std::invalid_argument& e) // D
{
// print error
continue;
}
catch (std::runtime_error& e) // C
{
// print error
continue;
}
}
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
}
catch (invalid_argument& e) // B
{
// print error
return 0;
}
}
catch (exception& e) // A
{
// print error
return 0;
}
设计 catch
的最佳方法是让它只捕获它知道如何在代码中的那个位置处理的 特定 类型的异常。让外部 catch
处理其他所有事情。如果抛出异常并且没有找到匹配的catch
来处理它,进程将默认终止。