C++核心准则E.2:通过抛出异常来表明函数无法执行指定的任务

面向对象思考

共 3898字,需浏览 8分钟

 ·

2020-07-27 18:19

E.2: Throw an exception to signal that a function can't perform its assigned task

E.2:通过抛出异常来表明函数无法执行指定的任务


Reason(原因)

To make error handling systematic, robust, and non-repetitive.

为了使用错误处理系统化,健壮和不繁琐。


Example(示例)

struct Foo {
vector v;
File_handle f;
string s;
};

void use()
{
Foo bar {{Thing{1}, Thing{2}, Thing{monkey}}, {"my_file", "r"}, "Here we go!"};
// ...
}

Here, vector and strings constructors may not be able to allocate sufficient memory for their elements, vectors constructor may not be able copy the Things in its initializer list, and File_handle may not be able to open the required file. In each case, they throw an exception for use()'s caller to handle. If use() could handle the failure to construct bar it can take control using try/catch. In either case, Foo's constructor correctly destroys constructed members before passing control to whatever tried to create a Foo. Note that there is no return value that could contain an error code.

这里vector和string的构造函数可能无法为它们的元素分配足够的内存,vector构造函数可能无法复制初始化列表中的内容,File_handle有可能无法打开需要的文件。每种情况中,它们都会向调用者抛出异常以便处理。如果use()可以处理构造bar对象时的错误,它们可以通过try/catry获得控制。其他情况下,Foo的构造函数可以在将控制权交给试图构建Foo的代码之前正确地销毁已经构造完成的成员。注意,代码中没有可以容纳错误码的返回值。

The File_handle constructor might be defined like this:

File_handle的构造函数可能被定义成下面的样子:

File_handle::File_handle(const string& name, const string& mode)
: f{fopen(name.c_str(), mode.c_str())}
{
if (!f)
throw runtime_error{"File_handle: could not open " + name + " as " + mode};
}
Note(注意)

It is often said that exceptions are meant to signal exceptional events and failures. However, that's a bit circular because "what is exceptional?" Examples:

一般情况下会认为异常意味着重大的例外事件和错误。然而,这个问题多少有点绕,到底什么是例外?例如:

  • A precondition that cannot be met

  • 一个前提条件没有满足

  • A constructor that cannot construct an object (failure to establish its class's invariant)

  • 构造函数无法构造对象(无法建立类的不变式)

  • An out-of-range error (e.g., v[v.size()] = 7)

  • 越界错误(例如 v[v.size()]=7)

  • Inability to acquire a resource (e.g., the network is down)

  • 无法获取资源(例如:网络断)

In contrast, termination of an ordinary loop is not exceptional. Unless the loop was meant to be infinite, termination is normal and expected.

相反,结束一个通常的循环不属于异常。只要它不是无限循环,中止就是正常和期待的。


Note(注意)

Don't use a throw as simply an alternative way of returning a value from a function.

不要使用将抛出异常作为从函数中返回结果的另一种方式使用。


Exception(例外)

Some systems, such as hard-real-time systems require a guarantee that an action is taken in a (typically short) constant maximum time known before execution starts. Such systems can use exceptions only if there is tool support for accurately predicting the maximum time to recover from a throw.

有些系统,例如硬实时系统要求保证一个动作在开始执行之前就能确定其执行时间小于某个固定值(通常很小)。这样的系统只有在存在某种可以准确预测系统从抛出异常过程中恢复的最大时间的工具时才可以使用异常。


See also: RAII

参见:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e6-use-raii-to-prevent-leaks

See also: discussion

参见:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#discussion-usage-of-noexcept


Note(注意)

Before deciding that you cannot afford or don't like exception-based error handling, have a look at the alternatives; they have their own complexities and problems. Also, as far as possible, measure before making claims about efficiency.

在决定你无法承担或者不喜欢基于例外的错误处理之前,考虑以下其他选项;它们包含自己的复杂性和问题。同时,只要可能的话,在抱怨效率问题之前进行测量。


原文链接https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e2-throw-an-exception-to-signal-that-a-function-cant-perform-its-assigned-task

新书介绍

以下是本人3月份出版的新书,拜托多多关注!


本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。




觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!



浏览 30
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报