简体   繁体   English

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

[英]What is the purpose of std::exception::what()?

I can only think of the following situations where std::exception::what() is used: 我只能想到以下使用std :: exception :: what()的情况:

  1. For debug purpose. 用于调试目的。 In my Visual Studio to see e.what() I have to manually add it to the watch list. 在我的Visual Studio中,要查看e.what(),我必须将其手动添加到监视列表。 Isn't it better to have a member std::string (so the debugger directly shows it in the object inspector), and only include it in non-NDEBUG builds? 拥有成员std :: string更好吗(调试器直接在对象检查器中显示它),并且仅将其包括在非NDEBUG构建中? At least they should disable what() in NDEBUG builds. 至少他们应该禁用NDEBUG构建中的what()。
  2. Output it, eg MessageBox(e.what()) or cout << e.what() . 输出它,例如MessageBox(e.what())cout << e.what() As far as I know these messages are useless for many users. 据我所知,这些消息对许多用户都没有用。 For example when I try to rename a file that doesn't exist: 例如,当我尝试重命名一个不存在的文件时:

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

    (The Chinese words means "The system cannot find the file specified.") How can the users decrypt the mixed things? (中文意思是“系统找不到指定的文件。”)用户如何解密混合的内容? Also, it is a const char* instead of something like const platform_char* , which may have unicode problems in Windows. 另外,它是const char*而不是const platform_char*类的东西,在Windows中可能会出现unicode问题。

  3. Extract data from it, eg std::regex_match(e.what()...) . 从中提取数据,例如std::regex_match(e.what()...) I think it's a terrible idea that shows design flaws. 我认为这是一个可怕的想法,显示出设计缺陷。

So where should I use std::exception::what()? 所以我应该在哪里使用std :: exception :: what()? Is it useless? 它没用吗?

A programmer is supposed to derive a class from std::exception and taylor what() to the specific requirements. 程序员应该从std::exception派生一个类,并根据特定需求选择what() Then it can be very useful. 然后它会非常有用。

It's also useful to report something back (eg in plain text for logging), which is why the standard mandates a concrete std::exception::what() rather than a pure virtual function. 这也是有用的报告后面的东西 (如以纯文本的日志记录),这就是为什么标准规定一个具体std::exception::what()而不是一个纯虚函数。

what() is generic in the sense that it means what you want it to mean for your own exception classes. what()是通用的,即它意味着您想要它对自己的异常类意味着什么。 In many cases it is used only for logging, but in other cases it may provide information that can be used to recover from an exceptional situation. 在许多情况下,它仅用于记录日志,但在其他情况下,它可能提供可用于从特殊情况中恢复的信息。

So where should I use std::exception::what()? 所以我应该在哪里使用std :: exception :: what()? Is it useless? 它没用吗?

The error message of std::exception is a char* because it's supposed to be an as-simple-as-possible user-facing diagnostics message giving details on the error. std :: exception的错误消息是char *,因为它应该是一种尽可能简单的面向用户的诊断消息,其中提供有关错误的详细信息。

For boost::system_error (and std::system_error), you can also get the OS-level error code (for which the user-friendly message is "file not found"). 对于boost :: system_error(和std :: system_error),您还可以获得操作系统级别的错误代码(其用户友好消息为“找不到文件”)。

Valid uses: 有效用途:

  • if you want to identify the error type, catch the specialization std::system_error or boost::system_error and perform a switch/if on the code() function (ie instead of running a regex on the message). 如果要确定错误类型,请捕获专业化std :: system_error或boost :: system_error并在code()函数上执行switch/if (即,而不是在消息上运行正则表达式)。

  • if you want to display an explanation of the error for diagnostics (logging) or user friendliness (to console/GUI) just display the error message ( what() ). 如果要显示诊断错误(日志记录)或用户友好性(对控制台/ GUI)的说明,只需显示错误消息( what() )。

  • std::exception is a base class (ie it has a virtual destructor). std :: exception是基类(即,它具有虚拟析构函数)。 If you implement your own exception classes, follow the same pattern as std::system_error: use an error code to easily identify an error, and create your exception's base class (std::exception, std::runtime_error or std::logic_error usually) with a text message depending on the error type. 如果实现自己的异常类,请遵循与std :: system_error相同的模式:使用错误代码轻松识别错误,并创建异常的基类(通常为std :: exception,std :: runtime_error或std :: logic_error ),并根据错误类型显示一条短信。

  • Ultimately, the type of the error message is char* instead of std::string, wstring or your-platform-specific-char-type because it sacrifices flexibility for reliability: with a char* everybody knows how to use it, that it has no encoding (except ASCII), that it's null terminated and once allocated, it does not fail (it doesn't generate new exceptions). 最终,错误消息的类型是char *而不是std :: string,wstring或您的平台特定的char-type,因为它牺牲了可靠性的灵活性:使用char *,每个人都知道如何使用它,它具有没有编码(ASCII除外),它以null终止,并且一旦分配,就不会失败(不会生成新的异常)。

Using something that could fail (in any way) when constructing an exception would be disastrous: you would fail while creating/using a diagnostics message of your error handling code. 在构造异常时使用可能会(以任何方式失败)的操作将是灾难性的:您将在创建/使用错误处理代码的诊断消息时失败。

This means you could either not throw the exception (and your application will remain in an invalid state), or throw an exception while creating an exception instance (you really don't want that as it would discard the exception you wanted to throw (hide errors) or throw an exception with a missing or corrupted error code (which could waste months of development time in various projects to track down the wrong error). 这意味着您要么不能抛出异常(应用程序将保持无效状态),要么在创建异常实例时抛出异常(您实际上不希望那样,因为它会丢弃您要抛出的异常(隐藏)错误)或抛出错误代码缺失或损坏的异常(这可能会浪费多个项目的开发时间来查找错误的错误)。

Consider this example (unnecessarily complicated, but it makes a point): 考虑以下示例(不必要地复杂,但是很重要):

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"));

The throw line will presumably fail: the application has so little memory available that it won't even allocate an int*, let alone a string. 引发异常的行可能会失败:该应用程序的可用内存很少,以至于它甚至不会分配int *,更不用说字符串了。 The result of this code is that in low memory conditions I will still get a std::out_of_memory error - one generated by std::string constructor. 这段代码的结果是,在内存不足的情况下,我仍然会收到一个std :: out_of_memory错误-由std :: string构造函数生成的错误。

std::exception is a good implementation: it provides a minimal extendable interface with a good management/restriction of failure points and it gives a good interface for extensions (such as std::system_error). std :: exception是一个很好的实现:它提供了最小的可扩展接口,并具有对故障点的良好管理/限制,并且为扩展(例如std :: system_error)提供了良好的接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM