异常捕获机制,C ++

时间:2016-09-11 18:44:45

标签: c++ c++11 exception

考虑以下代码:

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类型的异常并试图抓住它 逻辑上,由于类型不匹配(catchstd::bad_alloc),第一个std::range_error块无法捕获它。
第二个catch块必须捕获它,因为它们是std::range_error的相同类型 而且,当我在第二个catch块中重新抛出异常时,它必须在第三个catch块中被捕获。

所以我的输出必须是

BBB
CCC
DDD

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

有人能解释一下我的行为吗?

3 个答案:

答案 0 :(得分:6)

当您重新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;
}

一个异常处理块。因此,在满足任何throw块中的第一个catch时,它会使整个块在当前范围之外寻找另一个处理块( try-catch )。如果没有找到,程序将终止。

请参阅try-catch block in C++

按照您最初的想法打印... 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梯形图来控制流程的异常

答案 1 :(得分:5)

要重新捕获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

答案 2 :(得分:4)

throw

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

本身并不在try的主体内,所以当异常处理机制一次一个地继续运行时,直到找到一个。由于没有其他外部try,因此根本没有发现异常。

异常处理中没有重入。