std::exception::What()的目的是什么



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

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

    boost::filesystem::rename: 系统找不到指定的文件。: "D:MyDesktop4", "D:MyDesktop5"

    (中文意思是"系统找不到指定的文件"。)用户如何解密混合的东西?此外,它是const char*,而不是类似const platform_char*的东西,后者在Windows中可能存在unicode问题。

  3. 从中提取数据,例如std::regex_match(e.what()...)。我认为这是一个显示设计缺陷的糟糕想法

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

程序员应该根据特定需求从std::exception和taylor what()派生一个类。然后它会非常有用。

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

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

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

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

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

有效用途:

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

  • 如果您想显示错误的解释以用于诊断(日志记录)或用户友好性(到控制台/GUI),只需显示错误消息(what())。

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

  • 最终,错误消息的类型是char*,而不是std::string、wstring或您的平台特定的char类型,因为它牺牲了可靠性的灵活性:有了char*,每个人都知道如何使用它,它没有编码(除了ASCII),它是null终止的,一旦分配,它就不会失败(它不会生成新的异常)。

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

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

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

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)提供了良好的接口。

相关内容

最新更新