前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++核心准则C.42:如果构造函数不能生成合法对象就抛出异常

C++核心准则C.42:如果构造函数不能生成合法对象就抛出异常

作者头像
面向对象思考
发布2020-03-25 16:09:56
5340
发布2020-03-25 16:09:56
举报

C.42: If a constructor cannot construct a valid object, throw an exception C.42:如果构造函数不能生成合法对象就抛出异常

Reason(原因)

Leaving behind an invalid object is asking for trouble.

将无效对象留给后续处理就等于是自找麻烦。

Example(示例)

代码语言:javascript
复制
class X2 {
    FILE* f;
    // ...
public:
    X2(const string& name)
        :f{fopen(name.c_str(), "r")}
    {
        if (!f) throw runtime_error{"could not open" + name};
        // ...
    }

    void read();      // read from f
    // ...
};

void f()
{
    X2 file {"Zeno"}; // throws if file isn't open
    file.read();      // fine
    // ...
}

Example, bad(反面示例)

代码语言:javascript
复制
class X3 {     // bad: the constructor leaves a non-valid object behind
    FILE* f;   // call is_valid() before any other function
    bool valid;
    // ...
public:
    X3(const string& name)
        :f{fopen(name.c_str(), "r")}, valid{false}
    {
        if (f) valid = true;
        // ...
    }

    bool is_valid() { return valid; }
    void read();   // read from f
    // ...
};

void f()
{
    X3 file {"Heraclides"};
    file.read();   // crash or bad read!
    // ...
    if (file.is_valid()) {
        file.read();
        // ...
    }
    else {
        // ... handle error ...
    }
    // ...
}

Note(注意)

For a variable definition (e.g., on the stack or as a member of another object) there is no explicit function call from which an error code could be returned. Leaving behind an invalid object and relying on users to consistently check an is_valid() function before use is tedious, error-prone, and inefficient.

变量定义(例如在堆栈或者作为其他对象的成员)不存在用于返回错误代码的明确的函数调用。留给后续处理一个无效对象并且依靠用户在使用之前总是通过一个is_valid()函数进行检查的做法是乏味的,易错和低效的。

Exception(例外)

There are domains, such as some hard-real-time systems (think airplane controls) where (without additional tool support) exception handling is not sufficiently predictable from a timing perspective. There the is_valid() technique must be used. In such cases, check is_valid() consistently and immediately to simulate RAII.

有些领域,例如硬实时系统(例如飞机控制),它们(如果没有另外的工具支持)从时机的方面来讲异常处理不是充分可预测的。这里必须采用is_valid()技术。在这样的情况下,需要自始至终地检查is_valid()并且立刻模仿RAII的行为。

1.RAII是Resource Acquisition Is Initialization(wiki上面翻译成 “资源获取就是初始化”)的简称,是C++语言的一种管理资源、避免泄漏的惯用法。链接:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rr-raii

2.硬实时系统无法终端程序执行,因此无法抛出异常。

Alternative(其他选项)

If you feel tempted to use some "post-constructor initialization" or "two-stage initialization" idiom, try not to do that. If you really have to, look at factory functions.

如果想要使用前置条件初始化或者两阶段初始化,不要那么做。如果你真的必须那样做,考虑工厂函数。

工厂函数:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-factory

Note(注意)

One reason people have used init() functions rather than doing the initialization work in a constructor has been to avoid code replication.Delegating constructors and default member initialization do that better. Another reason has been to delay initialization until an object is needed; the solution to that is often not to declare a variable until it can be properly initialized。pa

人们使用init()函数而不是在构造函数内部进行初始化处理是希望避免代码重复。委托构造函数和默认成员初始化可以做地更好。另外一个原始是希望将对象的初始化延迟到它被使用之前;解决方法通常是等到变量可以被正确的初始化时在声明它。

委托构造函数:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-delegating

Enforcement(实施建议)

???

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c42-if-a-constructor-cannot-construct-a-valid-object-throw-an-exception


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

关注【面向对象思考】轻松学习每一天!

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 面向对象思考 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C.42: If a constructor cannot construct a valid object, throw an exception C.42:如果构造函数不能生成合法对象就抛出异常
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档