在不允许异常的环境中(例如在谷歌中),C++构造函数必须有效地成功,因为它们无法向调用方报告失败。当然,您可以使用abort(),但是这样做会使整个程序崩溃,这在生产代码中通常是不可接受的。

如果类的初始化逻辑无法避免失败的可能性,一种常见的方法是给类一个初始值设定项方法(也称为“init方法”),该方法执行任何可能失败的初始化工作,并通过其返回值通知失败。通常假定用户在构造后立即调用此方法,如果失败,则用户将立即销毁该对象。然而,这些假设并不总是记录在案,也不总是遵守。在初始化之前或初始化失败之后,用户很容易开始调用其他方法。有时,类实际上鼓励这种行为,例如,通过提供方法在初始化对象之前对其进行配置,或者在初始化失败后从中读取错误。

这种设计要求您维护一个类,该类至少具有两种不同的用户可见状态,通常有三种状态:初始化、未初始化和初始化失败。使这样的设计工作需要很多规则:类的每个方法都必须指定可以调用它的状态,并且用户必须遵守这些规则。如果这一原则失效,不管您打算支持什么,客户机开发人员都会倾向于编写任何代码。当这种情况开始发生时,可维护性就开始下降,因为您的实现必须支持客户机开始依赖的任何预初始化方法调用组合。实际上,您的实现已经成为您的接口。

幸运的是,有一个简单的替代方法缺少这些缺点:提供一个工厂函数,它创建并初始化类的实例,并通过指针或absl::optional(请参见TotW #123)返回它们,使用null表示失败。以下是一个使用unique_ptr<>例子:

// foo.h
class Foo {public:// Factory method: creates and returns a Foo.// May return null on failure.static std::unique_ptr<Foo> Create();// Foo is not copyable.Foo(const Foo&) = delete;Foo& operator=(const Foo&) = delete;private:// Clients can't invoke the constructor directly.Foo();
};// foo.c
std::unique_ptr<Foo> Foo::Create() {// Note that since Foo's constructor is private, we have to use new.return absl::WrapUnique(new Foo());
}

在许多情况下,此模式为您提供了两个方面的最佳选择:工厂函数foo::create()只公开完全初始化的对象(如构造函数),但它可以指示类似初始值设定项方法的失败。工厂函数的另一个优点是,它们可以返回返回类型的任何子类的实例(尽管如果使用absl::optional作为返回类型,则不可能这样做)。这允许您在不更新用户代码的情况下交换不同的实现,甚至可以基于用户input动态选择实现类。

这种方法的主要缺点是它返回一个指向堆分配对象的指针,因此它不太适合设计用于堆栈的“类值”类。然而,这样的类首先通常不需要复杂的初始化。当派生类构造函数需要初始化其基时,工厂函数也不能使用,因此在基类的受保护API中有时需要初始值设定项方法。不过,公共API仍然可以使用工厂函数。

Abseil之Prefer Factory Functions to Initializer Methods相关推荐

  1. Design Pattern - Factory Method(C#)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Defi ...

  2. ES6 Arrow functions

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions 一个箭头函数表达 ...

  3. Kotlin 编码规约

    Kotlin 编码规约 编码规范 本页包含当前 Kotlin 语言的编码风格. 源代码组织 命名规则 格式化 文档注释 避免重复结构 语言特性的惯用法 库的编码规范 应用风格指南 如需根据本风格指南配 ...

  4. Google JavaScript Style Guide

    转自:http://google.github.io/styleguide/javascriptguide.xml Google JavaScript Style Guide Revision 2.9 ...

  5. TSLint 配置规则

    TSLint core rules 原文:https://palantir.github.io/tslint/rules/ Lint rules encode logic for syntactic ...

  6. C++11 FAQ中文版

    C++11 FAQ中文版 http://www.chenlq.net/cpp11-faq-chs http://www.stroustrup.com/C++11FAQ.html Morgan Stan ...

  7. 转:PHP – Best Practises

    原文来自于:http://thisinterestsme.com/php-best-practises/ There are a number of good practises that you s ...

  8. gtest简介及简单使用

    gtest是一个跨平台(Liunx.Mac OS X.Windows.Cygwin.Windows CE and Symbian)的C++测试框架,有google公司发布.gtest测试框架是在不同平 ...

  9. JavaScript创建对象–如何在JS中定义对象

    Objects are the main unit of encapsulation in Object-Oriented Programming. In this article, I will d ...

最新文章

  1. 全球首个「活体机器人」生娃!100%青蛙基因,杀不死,可繁衍4世
  2. eccv2020 目标检测笔记
  3. 剑指offer十一:二进制中1的个数
  4. JVM-12虚拟机性能监控与故障处理工具之【JDK的可视化工具-VisualVM】
  5. 机器学习笔记GBDT(一):原理
  6. layui select 修改_layui修改select的值的方法
  7. 顶级俄国数学家是怎样炼成的?[2016-06-25 张羿 赛先生]
  8. mysql导出bacpac_数据库的迁移
  9. robotframework(12)修改用户密码(从数据库查询短信验证码)
  10. 还有人不知道什么是AndroidX的吗?文末领取面试资料
  11. Linux: Nginx 安装
  12. 消息称百度网盘青春版降速23倍:从52MB/s降至2.2MB/s
  13. 35款安卓App被通报窃取个人隐私!快看看你的手机里有没有
  14. 解决修改sources.list之后update NO_PUBKEY错误
  15. element-ui分页器的使用
  16. 【数据挖掘】基于密度的聚类方法 - OPTICS 方法 ( 算法流程 | 算法示例 )
  17. 如何使用Python3解二维码和编译二维码
  18. 抖音微信登录服务器繁忙,微信登录抖音失败解决方法介绍
  19. airtest获取设备号和获取设备宽度、高度、绝对坐标 相对坐标、滑动屏幕
  20. 李沐动手学深度学习第四章-4.9.环境和分布偏移

热门文章

  1. python绘制曲线y=2x+5_使用python动态生成波形曲线的实现
  2. 使用element-ui中的container布局容器
  3. c #include如何找到文件_使用 MATLAB Function 模块集成 C 代码
  4. python中 和 的区别_举例子让你明白python中is和==的区别
  5. mysql 编辑 条目,mysql函数:将旧条目旋转到归档表
  6. linux音频设备节点,Linux音频驱动之三:PCM设备的创建
  7. python列表添加对象_python list append命令 添加对象
  8. elk 概念整理 集群状态 - yellow
  9. HCNA-RS笔记-20171105-day03
  10. BootStarp的form表单的基本写法