std :: exception :: what()的目的是什么?

时间:2013-12-10 14:53:51

标签: c++ exception

我只能想到以下使用std :: exception :: what()的情况:

  1. 用于调试目的。在我的Visual Studio中查看e.what()我必须手动将其添加到监视列表中。拥有一个成员std :: string(因此调试器直接在对象检查器中显示它)并且只包含在非NDEBUG构建中是不是更好?至少他们应该禁用NDEBUG构建中的what()。
  2. 输出它,例如MessageBox(e.what())cout << e.what()。据我所知,这些消息对许多用户来说都是无用的。例如,当我尝试重命名不存在的文件时:

      

    boost::filesystem::rename: 系统找不到指定的文件。: "D:\MyDesktop\4", "D:\MyDesktop\5"

    (中文单词的意思是“系统找不到指定的文件。”)用户如何解密混合的东西?此外,它是const char*而不是像const platform_char*这样的东西,在Windows中可能会出现unicode问题。

  3. 从中提取数据,例如std::regex_match(e.what()...)。我认为显示设计缺陷是一个可怕的想法。
  4. 那么我应该在哪里使用std :: exception :: what()?它没用吗?

3 个答案:

答案 0 :(得分:4)

程序员应该从std::exception和taylor what()派生出一个类来满足特定要求。然后它可以非常有用。

报告某些内容也很有用(例如,以纯文本形式记录日志),这就是为什么标准要求具体的std::exception::what()而不是纯虚函数。

答案 1 :(得分:4)

what()在某种意义上是通用的,它意味着您希望它对您自己的异常类意味着什么。在许多情况下,它仅用于记录,但在其他情况下,它可能提供可用于从异常情况中恢复的信息。

答案 2 :(得分:2)

  

那么我应该在哪里使用std :: exception :: what()?它没用吗?

std :: exception的错误消息是char *,因为它应该是一个尽可能简单的面向用户的诊断消息,提供有关错误的详细信息。

对于boost :: system_error(和std :: system_error),您还可以获取操作系统级别的错误代码(用户友好的消息是“找不到文件”)。

有效用途:

  • 如果要识别错误类型,请捕获专门化std :: system_error或boost :: system_error并在switch/if函数上执行code()(即不运行正则表达式在消息上。)

  • 如果要显示诊断(日志记录)或用户友好性(到控制台/ GUI)的错误说明,只需显示错误消息(what())。

  • std :: exception是一个基类(即它有一个虚析构函数)。如果您实现自己的异常类,请遵循与std :: system_error相同的模式:使用错误代码轻松识别错误,并创建异常的基类(通常是std :: exception,std :: runtime_error或std :: logic_error) )根据错误类型使用短信。

  • 最终,错误消息的类型是char *而不是std :: string,wstring或your-platform-specific-char-type,因为它牺牲了可靠性的灵活性:使用char *每个人都知道如何使用它,它没有编码(ASCII除外),它是空终止的,一旦分配,它不会失败(它不会产生新的异常)。

在构造异常时使用可能失败的东西(以任何方式)将是灾难性的:在创建/使用错误处理代码的诊断消息时会失败。

这意味着您可以不抛出异常(并且您的应用程序将保持无效状态),或者在创建异常实例时抛出异常(您实际上不希望这样做,因为它会丢弃您想要的异常抛出(隐藏错误)或抛出错误代码丢失或损坏的异常(这可能会浪费几个月的开发时间来追踪错误的错误)。

考虑这个例子(不必要的复杂,但它提出了一个观点):

int * p = new(nothrow) int(10); // I want to throw a complicated
                                // string message exception
if(nullptr == p)
    throw complicated_exception(std::string("error message here"));

抛出线可能会失败:应用程序的内存很少,甚至不会分配int *,更不用说字符串了。这段代码的结果是在低内存条件下我仍然会得到一个std :: out_of_memory错误 - 一个由std :: string构造函数生成的错误。

std :: exception是一个很好的实现:它提供了一个最小的可扩展接口,具有良好的故障点管理/限制,并为扩展提供了良好的接口(例如std :: system_error)。