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 ...
随机推荐
- [hdu6051]If the starlight never fade-[欧拉函数+原根]
Description 传送门 Solution orz大佬yxq..本题神仙 设g为P的原根. 设$x=g^{a}$,$y=g^{b}$. 由于$(g^{a}+g^{b})^{i}\equiv (g ...
- CF 1093 E. Intersection of Permutations
E. Intersection of Permutations 链接 题意: 给定两个序列,询问第一个排列的[l1,r1]和第二个排列[l2,r2]中有多少个共同的数,支持在第二个排列中交换两个数. ...
- ELKStack入门篇(四)之Filebeat
Filebeat是轻量级单用途的日志收集工具,用于在没有安装java的服务器上专门收集日志,可以将日志转发到logstash.elasticsearch或redis等场景中进行下一步处理. 官方文档: ...
- mybatis mapper空指针异常的问题
发现是因为mysql表名不能为 x_x_x 这样的形式,最多只能有一个下划线,不能有多个,否则会找不到数据,进而导致空指针异常 上面的被推翻了,发现原来是因为没有注入mapper才导致空指针异常! ...
- javaweb(三十九)——数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- Selenium自动化测试第二天(上)
如有任何学习问题,可以添加作者微信:lockingfree 目录 Selenium自动化测试基础 Selenium自动化测试第一天(上) Selenium自动化测试第一天(下) Selenium自动化 ...
- HTML从入门到放弃
一.HTML 简介 链接:https://www.cnblogs.com/baishuchao/articles/9179920.html 二.HTML 基础 链接:https://www.cnblo ...
- PHP原生代码写的微信扫码支付实例
一款PHP原生代码写的微信扫码支付,不基于任何框架,完全手写. 扫码支付只要授权域名对就OK,本地是无法测试.跟openid也没有关系,所以跟支付授权目录页没关系. 微信商户信息配置地址:weixin ...
- idea compare功能 之一次bug修复
一次bug修复 最近开发完了一套单点系统,jenkins打包上传到服务器就出问题, 可以启动但是不能正常工作. 首先想到的是环境不一样, 于是把jenkins的jdk和maven都调整和本机大版本相同 ...
- cs231n学习笔记(一)计算机视觉及其发展史
在网易云课堂上学习计算机视觉经典课程cs231n,觉得有必要做个笔记,因为自己的记性比较差,留待以后查看. 每一堂课都对应一个学习笔记,下面就开始第一堂课. 这堂课主要是回顾了计算机视觉的起源及其后来 ...