代码之家  ›  专栏  ›  技术社区  ›  John M Gant aman_novice

我应该从std::exception继承吗?

  •  94
  • John M Gant aman_novice  · 技术社区  · 15 年前

    我已经看到至少一个可靠的源(C++ C++类)建议C++中的应用程序特定异常类应该继承 std::exception . 我不清楚这种方法的好处。

    ApplicationException 很清楚:您可以获得一些有用的方法、属性和构造函数,只需添加或覆盖所需的内容。具有 异常 看来你得到的只是一个 what() 方法进行重写,您也可以自己创建。

    那么,如果有的话,使用 异常 异常 ?

    14 回复  |  直到 15 年前
        1
  •  71
  •   Nikolai Fetissov    15 年前

    throw 看吧,但我可以 catch 这个 std::exception .

    正如Martin和其他人所指出的,您实际上希望从 异常 声明于 <stdexcept>

        2
  •  41
  •   Keith Pinson sumit vedi    11 年前

    问题在于 std::exception 就是没有接受消息的构造函数(在符合标准的版本中)。

    因此,我更喜欢从 std::runtime_error 异常 但它的构造函数允许您传递C字符串或 std::string 将返回的构造函数(作为 char const* what()

        3
  •  17
  •   Aleksei Potov    15 年前

    继承原因 std::exception 异常

    如果你是为了方便,你可以继承 std::runtime_error std::string 构造器。

        4
  •  13
  •   timday    15 年前

    我曾经参与清理一个大型代码库,以前的作者在这里抛出int、HRESULTS、std::string、char*、random类。。。到处都是不同的东西;只要说出一个类型,它就可能被扔到某个地方。而且根本没有公共基类。相信我,一旦我们达到了这样的程度,所有抛出的类型都有一个共同的基础,我们可以抓住,并且知道没有什么会过去,事情就变得更加整洁了。所以,请帮你自己(以及那些将来需要维护你的代码的人)一个忙,从一开始就这样做。

        5
  •  12
  •   James Schek    15 年前

    你应该继承他的遗产 boost::exception Boost ,然后忽略这个建议。

        6
  •  11
  •   cbuchart    7 年前

    是的,你应该从 std::exception

    异常 存在无法向其传递文本消息的问题,但是在抛出时尝试格式化用户消息通常不是一个好主意。相反,使用exception对象将所有相关信息传输到catch站点,然后catch站点可以格式化用户友好的消息。

        7
  •  9
  •   SingleNegationElimination    15 年前

    您可能希望从中继承遗产的原因 std::exception 是因为它允许您抛出根据该类捕获的异常,即:

    class myException : public std::exception { ... };
    try {
        ...
        throw myException();
    }
    catch (std::exception &theException) {
        ...
    }
    
        8
  •  6
  •   Jean-François Fabre    7 年前

    throw e; throw . 那可能不是你所期望的。您可以找到的问题示例 here .

        9
  •  5
  •   Community Mr_and_Mrs_D    7 年前

    Difference: std::runtime_error vs std::exception()

    无论你 应该 继承与否取决于你自己。标准 std::exception 它的标准后代提出了一种可能的异常层次结构(划分为 logic_error runtime_error

        10
  •  3
  •   user3458 user3458    15 年前

    由于该语言已经抛出std::exception,因此无论如何都需要捕获它以提供适当的错误报告。您也可以对自己的所有意外异常使用相同的捕获。而且,几乎任何抛出异常的库都会从std::exception派生它们。

    catch (...) {cout << "Unknown exception"; }
    

    catch (const std::exception &e) { cout << "unexpected exception " << e.what();}
    

        11
  •  3
  •   Mark Ransom    15 年前

    如果所有可能的异常都来自 std::exception ,您的捕捉块可以简单地 catch(std::exception & e) 并确保捕获一切。

    what 方法以获取更多信息。C++不支持鸭式输入,所以另一个类用 什么 方法将需要不同的catch和不同的代码来使用它。

        12
  •  3
  •   Rob    13 年前

    是否从任何标准异常类型派生是第一个问题。这样做可以为所有标准库异常和您自己的异常启用单个异常处理程序,但它也鼓励这样的捕获所有异常处理程序。问题在于,人们应该只捕获自己知道如何处理的异常。例如,在main()中,如果在退出之前作为最后手段记录what()字符串,那么捕获所有std::异常可能是一件好事。然而,在其他地方,这不太可能是个好主意。

        13
  •  0
  •   James Burnby    11 年前

    创建子类异常的另一个原因是在处理大型封装系统时有更好的设计。您可以将其重新用于验证消息、用户查询、严重控制器错误等。您可以简单地在主源文件上“捕获”所有类似验证的消息,而不是重写或重新hook所有消息,而是在整个类集中的任何位置抛出错误。

    e、 g.致命异常将终止程序,验证错误只会清除堆栈,用户查询将向最终用户提问。

    这样做还意味着您可以在不同的接口上重用相同的类。e、 windows应用程序可以使用消息框,web服务将显示html,报告系统将记录它,等等。

        14
  •  0
  •   GPMueller    7 年前

    使用 std::nested_exception std::throw_with_nested

    它在StackOverflow上描述 here here 获取异常的回溯跟踪 只需编写一个适当的异常处理程序,它将重新显示嵌套的异常,就可以在代码内部执行,而无需调试器或繁琐的日志记录。

    你也可以看看我的 MWE on GitHub ,其中回溯跟踪的外观如下所示:

    Library API: Exception caught in function 'api_function'
    Backtrace:
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
    ~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
    

    std::runtime_error

    我在子类化(而不仅仅是使用 )您的异常处理程序可以捕获自定义异常并执行一些特殊的操作。例如:

    try
    {
      // something that may throw
    }
    catch( const MyException & ex )
    {
      // do something specialized with the
      // additional info inside MyException
    }
    catch( const std::exception & ex )
    {
      std::cerr << ex.what() << std::endl;
    }
    catch( ... )
    {
      std::cerr << "unknown exception!" << std::endl;
    }