专栏首页C++核心准则原文翻译C++核心准则C.42:如果构造函数不能生成合法对象就抛出异常

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

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(示例)

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(反面示例)

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


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

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

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

本文分享自微信公众号 - 面向对象思考(OOThinkingDalian),作者:面向对象思考

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++核心准则CP.26:不要分离线程

    Often, the need to outlive the scope of its creation is inherent in the threads ...

    面向对象思考
  • C++核心准则​GSL.view:视图

    These types allow the user to distinguish between owning and non-owning pointers...

    面向对象思考
  • C++核心准则ES.56​:只在需要将一个对象显式移动到另外的作用域时使用std::move​

    We move, rather than copy, to avoid duplication and for improved performance.

    面向对象思考
  • 目前最全的R语言-图片的组合与拼接

    李誉辉,四川大学硕士在读,研究数据分析与可视化,以及网络爬虫。誉辉兄最近出的文章都是很系统的,从R ggplot2的基础讲解到三维数据可视化plot3D,文章都...

    生信宝典
  • java程序员编程语言学习:最低成本解决bug的方法

    Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、...

    java架构师
  • ES6之Iterator遍历器

    遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据...

    wade
  • win10 uwp 禁用 ScrollViewer 交互

    如果在 UWP 有一个控件里面有 ScrollViewer 控件,那么因为默认的 ScrollViewer 会使用触摸的交互,这样在控件就收不到触摸的交互

    林德熙
  • Android中RecyclerView的item宽高问题详解

    本文主要给大家介绍了关于Android中RecyclerView的item宽高问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

    砸漏
  • Python脚本BUG引发学界震动,影响有多大?

    近日一篇“A guide to small-molecule structure assignment through computation of (1H a...

    AI科技大本营
  • 第二篇:SpringBoot高级-整合redis作为缓存

    版权声明:本文为博主原创文章,未经博主允许不得转载。 ...

    用户1212940

扫码关注云+社区

领取腾讯云代金券