【问题标题】:Error with catching std::runtime_error as std::exception将 std::runtime_error 捕获为 std::exception 时出错
【发布时间】:2011-04-16 06:50:30
【问题描述】:

try catch 和 std::runtime_error 有一个有趣的问题。 有人可以向我解释为什么这会返回“未知错误”作为输出吗? 非常感谢您帮助我!

#include "stdafx.h"
#include <iostream>
#include <stdexcept>

int magicCode()
{
    throw std::runtime_error("FunnyError");
}

int funnyCatch()
{
    try{
        magicCode();
    } catch (std::exception& e) {
        throw e;
    }

}

int _tmain(int argc, _TCHAR* argv[])
{
    try
    {
        funnyCatch();
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
    }
 return 0;
}

【问题讨论】:

  • 它使用 Visual C++ 2010 为我打印“FunnyError”。您使用的是哪个编译器?

标签: c++ exception try-catch


【解决方案1】:

我找到了对这个问题的完美回应:

C++ 明确区分了引用和值副本。使用

catch (const std::exception& e) 

通过引用而不是值来捕获。

去为原始响应者here投赞成票

【讨论】:

  • 我没有按值复制。
【解决方案2】:

问题在于这条线。因为带有表达式的throw 使用该表达式的静态类型来确定抛出的异常,所以这会分割异常对象,构造一个新的std::exception 对象,仅复制std::runtime_error 的基础对象部分,e 是一个引用到。

throw e;

要重新抛出捕获的异常,您应该始终使用不带表达式的 throw。

throw;

【讨论】:

  • 快了 18 秒……他是怎么做到的?!
  • 啊,exception 的复制构造函数不必保留what()。我没有意识到这一点。
  • 查尔斯,我还以为扔e;将调用复制构造函数 std::exception(const std::exception e),这将创建异常的正确副本?不是这样吗?
  • 是的,它使用std::exception的复制构造函数。不,这不一定会导致异常的“正确”副本,因为 std::exception 只是 e 实际引用的异常的基类。
  • 感谢您的完整回答,我被教导总是使用 throw 重新抛出,在调查问题时,我很好奇为什么 what() 返回的消息没有被保留。谢谢你,我知道原因了,查尔斯!
猜你喜欢
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
相关资源
最近更新 更多