C++解析(15):二阶构造模式
0.目录
1.构造函数与半成品对象
2.二阶构造
3.小结
1.构造函数与半成品对象
关于构造函数:
- 类的构造函数用于对象的初始化
- 构造函数与类同名并且没有返回值
- 构造函数在对象定义时自动被调用
问题:
- 如何判断构造函数的执行结果?
- 在构造函数中执行return语句会发生什么?
- 构造函数执行结束是否意味着对象构造成功?
(没有办法判断构造函数的执行结果,构造函数执行结束不意味着对象构造成功)
用一个状态来表示对象是否构造成功:
#include <stdio.h>
class Test
{
int mi;
int mj;
bool mStatus;
public:
Test(int i, int j) : mStatus(false)
{
mi = i;
return;
mj = j;
mStatus = true;
}
int getI()
{
return mi;
}
int getJ()
{
return mj;
}
int status()
{
return mStatus;
}
};
int main()
{
Test t1(1, 2);
if( t1.status() )
{
printf("t1.mi = %d\n", t1.getI());
printf("t1.mj = %d\n", t1.getJ());
}
return 0;
}
输出结果为空。
构造函数:
- 只提供自动初始化成员变量的机会
- 不能保证初始化逻辑一定成功
- 执行return语句后构造函数立即结束
构造函数能决定的只是对象的初始状态,而不是对象的诞生!!
半成品对象的概念:
- 初始化操作不能按照预期完成而得到的对象
- 半成品对象是合法的C++对象,也是Bug的重要来源
2.二阶构造
工程开发中的构造过程可分为:
- 资源无关的初始化操作
- 不可能出现异常情况的操作
- 需要使用系统资源的操作
- 可能出现异常情况,如:内存申请,访问文件
二阶构造:

二阶构造示例一:

二阶构造示例二:

示例代码:
#include <stdio.h>
class TwoPhaseCons
{
private:
TwoPhaseCons() // 第一阶段构造函数
{
}
bool construct() // 第二阶段构造函数
{
return true;
}
public:
static TwoPhaseCons* NewInstance(); // 对象创建函数
};
TwoPhaseCons* TwoPhaseCons::NewInstance()
{
TwoPhaseCons* ret = new TwoPhaseCons();
// 若第二阶段构造失败,返回 NULL
if( !(ret && ret->construct()) )
{
delete ret;
ret = NULL;
}
return ret;
}
int main()
{
TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
printf("obj = %p\n", obj);
delete obj;
return 0;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
obj = 0xd4f010
若是二阶构造失败了呢?
#include <stdio.h>
class TwoPhaseCons
{
private:
TwoPhaseCons() // 第一阶段构造函数
{
}
bool construct() // 第二阶段构造函数
{
return false;
}
public:
static TwoPhaseCons* NewInstance(); // 对象创建函数
};
TwoPhaseCons* TwoPhaseCons::NewInstance()
{
TwoPhaseCons* ret = new TwoPhaseCons();
// 若第二阶段构造失败,返回 NULL
if( !(ret && ret->construct()) )
{
delete ret;
ret = NULL;
}
return ret;
}
int main()
{
TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
printf("obj = %p\n", obj);
delete obj;
return 0;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
obj = (nil)
会返回一个空。
使用二阶构造模式后,对象只能在堆空间上创建,不能在栈上产生了。这恰恰是工程里面最重要的一个决定,因为在工程中,对象往往是比较巨大的,不适合放在栈空间当中,都应该放到堆空间里面去。
3.小结
- 构造函数只能决定对象的初始化状态
- 构造函数中初始化操作的失败不影响对象的诞生
- 初始化不完全的半成品对象是Bug的重要来源
- 二阶构造人为的将初始化过程分为两部分
- 二阶构造能够确保创建的对象都是完整初始化的
C++解析(15):二阶构造模式的更多相关文章
- C++之二阶构造模式
前言:C++中经常会因为调用系统资源失败导致出现BUG,所以在类调用构造函数需要分配系统资源时会出现BUG,从而导致类对象虽然被创建,但是只是个半成品,为了避免这种情况需要使用二阶构造模式 二阶构造模 ...
- C++ 二阶构造模式
1.如何判断构造函数的执行结果? 构造函数没有返回值,所以不能通过返回值来判断是构造函数是否构造成功. 如果给构造函数强行加入一个返回值,用来表示是否构造成功.这样确实能够反映出构造的结果,但是不够优 ...
- 14.C++-二阶构造模式、友元(详解)
首先回顾以前所学的构造函数 类的构造函数用于对象的初始化 构造函数与类同名并且没有返回值 构造函数在定义时被自动调用 由于构造函数没有返回值不能判断执行结果,所以不能保证初始化对象能否成功 比如: c ...
- Spark Streaming揭秘 Day34 解析UI监听模式
Spark Streaming揭秘 Day34 解析UI监听模式 今天分享下SparkStreaming中的UI部分,和所有的UI系统一样,SparkStreaming中的UI系统使用的是监听器模式. ...
- 第15章 迭代器模式(Iterator Pattern)
原文 第15章 迭代器模式(Iterator Pattern) 迭代器模式(Iterator Pattern) 概述: 在面向对象的软件设计中,我们经常会遇到一类集合对象,这类集合对象的内部结构 ...
- 【省带宽、压成本专题】深入解析 H.265 编码模式,带你了解 Apple 全面推进 H.265 的原因
过去几年,又拍云一直在点播.直播等视频应用方面潜心钻研,取得了不俗的成果.我们结合点播.直播.短视频等业务中的用户场景,推出了"省带宽.压成本"系列文章,从编码技术.网络架构等角度 ...
- JSON.stringify()方法是将一个javascript值(对象或者数组)转换成为一个JSON字符串;JSON.parse()解析JSON字符串,构造由字符串描述的javascript值或对象
JSON.stringify()方法是将一个javascript值(对象或者数组)转换成为一个JSON字符串:JSON.parse()解析JSON字符串,构造由字符串描述的javascript值或对象
- Java设计模式(15)备忘录模式(Memento模式)
Memento定义:memento是一个保存另外一个对象内部状态拷贝的对象,这样以后就可以将该对象恢复到原先保存的状态. Memento模式相对也比较好理解,我们看下列代码: public class ...
- javascript创建对象之函数构造模式和原型模式结合使用(四)
创建自定义类型的常见方式就是组合使用构造函数模式与原型模式一起使用. 构造函数模式用于定义实例对象的特有的部分(属性和方法),原型模式用于定义共享的部分. 这样最大限度的节省了内存的开销. funct ...
随机推荐
- 【LG4091】[HEOI2016/TJOI2016]求和
[LG4091][HEOI2016/TJOI2016]求和 题面 要你求: \[ \sum_{i=0}^n\sum_{j=0}^iS(i,j)*2^j*j! \] 其中\(S\)表示第二类斯特林数,\ ...
- Java读取Propertity文件
读取propertity 文件其实很简单,就是每次容易搞错文件路径,今天刚好项目又用到了,顺便记下来,以便以后参考: 目录如下: 代码如下: package com.infs.exam.process ...
- vue 3.0使用 BUG解决
最近在做vue的项目,吊进了很多坑,这些坑很浅,但一旦掉进去了,不花点功夫还爬不出来.所以总结下,当做下笔记,持续更新 1.<router-link> 里加的事件没反应 错误代码: < ...
- L016-linux系统文件权限体系实战深入讲解小节
L016-linux系统文件权限体系实战深入讲解小节 不知道今天能不能写完哈,能写完发出来就是这周发两次小结了,有进步哦,不过L015和L016两节课内容也确实不多,进入正题 上一课学到了chmod. ...
- Spring学习(五)-----注入bean属性的三种方式( 1: 正常的方式 2: 快捷方式 3: “p” 模式)
在Spring中,有三种方式注入值到 bean 属性. 正常的方式 快捷方式 “p” 模式 看到一个简单的Java类,它包含两个属性 - name 和 type.稍后将使用Spring注入值到这个 b ...
- 原生js使用ajax
AJAX 可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容(默认是异步) (1)使用ajax会用到XMLHttpRequest()对象 (2)然后使用open方法定义请求方法和请求 ...
- 【ZABBIX】SNMPtrap实现主动监控的原理与安装配置
工欲善其事,必先利其器.作为一款强大的开源软件,Zabbix号称“Monitor Everything”,其所依赖的,很大程度上便是SNMP的数据采集支持.SNMP 协议是用来管理设备的协议,目前SN ...
- 如何在HPUX的终端提示符前显示当前登录用户信息和所在目录
修改/etc/default/profile文件,在最后加上如下内容: case $LOGNAME in 'root') PS1="$LOGNAME@$(hostname): ...
- hbase实战——(1.1 nosql介绍)
什么是nosql NoSQL(NoSQL = Not Only SQL),意思是不仅仅是SQL的扩展,一般指的是非关系型的数据库. 随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0 ...
- 分布式数据库中间件Mycat百亿级数据存储(转)
此文转自: https://www.jianshu.com/p/9f1347ef75dd 2013年阿里的Cobar在社区使用过程中发现存在一些比较严重的问题,如高并发下的假死,心跳连接的故障,只实现 ...