异常捕获机制,c++

Exception catching mechanism, C++

本文关键字:c++ 机制 异常      更新时间:2023-10-16

考虑以下代码:

int main()
{
    try 
    {
        throw std::range_error("");
    }
    catch (std::bad_alloc) 
    {
        std::cout << "AAAA" << std::endl;
        throw;
    }
    catch (std::range_error) 
    {
        std::cout << "BBB" << std::endl;
        throw;
    }
    catch (std::exception)
    {
        std::cout << "CCC" << std::endl;
    }
    std::cout << "DDD" << std::endl;
}

这里我抛出一个类型为std::range_error的异常,并试图捕获它。
逻辑上,第一个catch块不能捕获它,因为类型不匹配(std::bad_allocstd::range_error)。
第二个catch块必须捕获它,因为它们是std::range_error的相同类型。
而且,当我在第二个catch块中重新抛出异常时,它必须在第三个catch块中被捕获。

所以我的输出必须是
BBB
CCC
DDD

但我只得到BBB输出与终止。

谁能给我解释一下这种行为?

当您re- throw一个异常时,您将它完全抛出当前异常处理块....的上下文中

try 
{
    throw std::range_error("");
}
catch (std::bad_alloc) 
{
    std::cout << "AAAA" << std::endl;
    throw;
}
catch (std::range_error) 
{
    std::cout << "BBB" << std::endl;
    throw;
}
catch (std::exception)
{
    std::cout << "CCC" << std::endl;
}

一个异常处理块。因此,在遇到catch块中的第一个throw时,它离开整个块,在当前作用域之外寻找另一个处理块(try-catch)。如果没有找到,程序终止。

请参见c++中的try-catch

按您最初的想法打印…Live On Coliru…

int main()
{
    try{
        try{
            try{
                throw std::range_error("");
            }
            catch (std::bad_alloc) {
                std::cout << "AAAA" << std::endl;
                throw;
            }
        }
        catch (std::range_error) {
            std::cout << "BBB" << std::endl;
            throw;
        }
    }
    catch (std::exception){
        std::cout << "CCC" << std::endl;
    }
    std::cout << "DDD" << std::endl;
}

打印:

BBB
CCC
DDD

记录:请避免在生产代码中使用简单的if-else梯子可以完成的控制流使用异常

要重新捕获range_error,需要新的外部try catch块。

#include <iostream>
int main()
{
  //outer try catch ------------------------
  try { 
    // inner try catch ---------------------
    try 
    {
      throw std::range_error("");
    }
    catch (std::bad_alloc) 
    {
      std::cout << "AAAA" << std::endl;
      throw;
    }
    catch (std::range_error) 
    {
      std::cout << "BBB" << std::endl;
      throw;
    }
    // -------------------------------
  }
  catch (std::exception)
  {
    std::cout << "CCC" << std::endl;
  }
  // --------------------------------
  std::cout << "DDD" << std::endl;
}

输出
BBB
CCC
DDD

This throw:

catch (std::range_error) 
{
    std::cout << "BBB" << std::endl;
    throw; // <== this one
}

本身并不在try的主体内,因此异常处理机制将每次持续走出一个作用域,直到找到一个为止。由于没有其他外部try,因此根本不会捕获异常。

异常处理中没有重入口。