二阶构造设计模式

目录

构造函数回顾

深入思考

实验

构造函数的真相

半成品对象

引入二阶构造设计模式

设计理念

二阶构造设计模式图

二阶构造示例

完整demo

小结


构造函数回顾

  1. 类的构造函数用于对象的初始化。
  2. 构造函数与类同名并且没有返回值。
  3. 构造函数在对象定义时自动被调用

深入思考

  1. 如何判断构造函数的执行结果?
  2. 在构造函数中执行 return 语句会发生什么?
  3. 构造函数执行结束是否意味着对象构造成功?

实验

test.cpp

#include <stdio.h>

class Test
{
    private:
        int mi;
        int mj;
    public:
        Test(int i,int j)
        {
            mi=i;
            mj=j;
        }
        
        int getI()
        {
            return mi;
        }
        
        int getJ()
        {
            return mj;
        }
};

int main()
{
    Test t1(1,2);
    
    printf("t1.mi = %d\n",t1.getI());
    printf("t1.mj = %d\n",t1.getJ());
    
    return 0;
}

编译运行,实验结果符合预期。

delphi@delphi-vm:~/c_c++$ g++ test.cpp -o test.out
delphi@delphi-vm:~/c_c++$ ./test.out 
t1.mi = 1
t1.mj = 2

接下来在构造函数中,加入 return语句,实验结果如下所示:

test.cpp

#include <stdio.h>

class Test
{
    private:
        int mi;
        int mj;
    public:
        Test(int i,int j)
        {
            mi=i;
            return ;
            mj=j;
        }
        
        int getI()
        {
            return mi;
        }
        
        int getJ()
        {
            return mj;
        }
};

int main()
{
    Test t1(1,2);
    
    printf("t1.mi = %d\n",t1.getI());
    printf("t1.mj = %d\n",t1.getJ());
    
    return 0;
}

编译运行,实验结果如下,可以看到 mj的值为随机数了。

delphi@delphi-vm:~/c_c++$ g++ test.cpp -o test.out
delphi@delphi-vm:~/c_c++$ ./test.out 
t1.mi = 1
t1.mj = 12783604

以上结果,可以看到:构造函数出现问题了,但是对象依旧诞生了,那么这个对象是一个合法的对象吗?

构造函数的真相

  1. 构造函数只提供自动初始化成员变量的机会。
  2. 构造函数不能保证初始化逻辑一定会成功。
  3. 执行 return 语句后构造函数立即结束。
  4. 构造函数能决定的只是对象的初始状态,而不能决定对象是否诞生。

半成品对象

  1. 初始化操作不能按照预期完成而得到的对象。
  2. 半成品对象是合法的C++对象,也是Bug的重要来源。

引入二阶构造设计模式

设计理念

工程开发中的构造过程可以分为:

        一:资源无关的初始化操作

                不可能出现异常情况的操作

        二:需要使用系统资源的操作

                可能出现异常情况,如:内存申请,访问文件

二阶构造设计模式图

从设计层面,将构造过程一分为二,第一阶段的构造做资源无关的操作,第二阶段做资源申请的操作。用二阶设计模式要么产生一个完整合法的C++对象,要么直接返回NULL,不会产生一个半成品的C++对象。

二阶构造示例

class TwoPhaseCons
{
    private:
        TwoPhaseCons(){  //第一阶段的构造函数
               
        }
        
        bool construct(){ //第二阶段的构造函数
        
        }
    public:
        static TwoPhaseCons* NewInstance(); //创建对象函数
};

TwoPhaseCons* TwoPhaseCons::NewInstance()
{
    TwoPhaseCons* ret = new TwoPhaseCons();
    
    //如果第二阶段构造失败,返回NULL
    if(!(ret && ret->construct()))
    {
        delete ret;
        ret = NULL;
    }
    
    return ret;
}

完整demo

#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(int argc,char* argv[])
{
    TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
    
    printf("obj = %p\n",obj);
    
    
    delete obj;
    
    return 0;
}


小结

  1. 构造函数只能够决定对象的初始化状态。
  2. 构造函数中初始化操作的失败不影响对象的诞生。
  3. 初始化不完全的半成品对象是Bug的重要来源。
  4. 二阶构造人为的将初始化过程分为两部分。
  5. 二阶构造能够确保创建的对象都是完整初始化的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/327648.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《机器人学一(Robotics(1))》_台大林沛群 第4周 Quiz4

前两题主要是细心观察即可&#xff0c;第三题主要是使用勾股定理以及简单的反三角函数求解即可&#xff0c;长度与角度答案分别为80和30&#xff0c;不作赘述&#xff0c;主要阐述从第四题开始的解题过程。 目录 P4.P5 - P7.P8. P4. 根据上述推导过程编写代码如下: import num…

nn.BCEWithLogitsLoss中weight参数和pos_weight参数的作用及用法

nn.BCEWithLogitsLoss中weight参数和pos_weight参数的作用及用法 weight参数pos_weight参数 weight参数 上式是nn.BCEWithLogitsLoss损失函数的计算公式&#xff0c;其中w_n对应weight参数。 如果我们在做多分类任务&#xff0c;有些类比较重要&#xff0c;有些类不太重要&…

Java实现城市桥梁道路管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥梁4.2 新增城市桥梁4.3 编辑城市桥梁4.4 删除城市桥梁4.5 查询单个城市桥梁 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的城市桥梁道路管理系统&#xff0c;支持…

项目压测优化实践思路

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

Vue入门六(前端路由的概念与原理|Vue-router简单使用|登录跳转案例|scoped样式|混入(mixin)|插件)

文章目录 前要&#xff1a;前端路由的概念与原理1&#xff09;什么是路由2&#xff09;SPA与前端路由3&#xff09;什么是前端路由4&#xff09;前端路由的工作方式 一、Vue-router简单使用1&#xff09;什么是vue-router2) vue-router 安装和配置的步骤① 安装 vue-router 包②…

【MATLAB源码-第112期】基于matlab的IDMA系统仿真,输出误码率和误块率,采用turbo编码。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 IDMA&#xff08;交织多址接入&#xff09;系统详细描述 1. 基本原理&#xff1a; - IDMA是一种基于码分多址&#xff08;CDMA&#xff09;的通信技术&#xff0c;它通过为每个用户分配一个独特的交织模式来实现用户之间…

vue前端开发自学基础,动态切换组件的显示

vue前端开发自学基础,动态切换组件的显示&#xff01;这个是需要借助于&#xff0c;一个官方提供的标签&#xff0c;名字叫【Component】-[代码demo:<component :is"ComponetShow"></component>]。 下面看看代码详情。 <template><h3>动态…

eureka进行服务注册

1.引入依赖 在想要在eureka注册的服务的pom.xml文件中引入eureka客户端依赖 <!--eureka客户端依赖--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> …

canvas创建图像数据,并在画布上展示

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

QT上位机开发(进度条操作)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 进度条是一个比较常见的控件。如果某个操作需要很长的时间才能完成&#xff0c;那么这个时候最好有一个进度条提示&#xff0c;这样比较容易平复一…

价值7500的在线授权网站源码支持IP+域名+双向授权全开源

PHP授权验证更新系统完整版&#xff0c;一键更新系统&#xff0c;一键卡密生成自助授权功能&#xff0c;域名ip双重验证功能等等 修复盗版检测&#xff0c;确保实时查看盗版 修复在线加密系统&#xff0c;一键加密 授权系统几乎所有的程序都能整合使用,包括您的app和计算机程序…

OpenCV——八邻域断点检测

目录 一、理论基础1、八邻域2、断点检测 二、代码实现三、结果展示四、参考链接 OpenCV——八邻域断点检测由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、理论基础 1、八邻域 图1 八邻域示意图 图…

debian12部署Gitea服务

首先安装git、wget、sqlite&#xff0c;然后进行用户和组的相关设置 sudo apt install -y git wget sqlite3 新增一个git用户与一个git组 sudo adduser --system --group --disabled-password --shell /bin/bash --home /home/git --gecos Git Version Control git 给git用户设…

Echarts 对饼状图上的各模块添加点击事件

文章目录 需求分析 需求 实现 echarts 中饼图点击区块事件 分析 当用户点击饼状图上的各个模块时&#xff0c;我们可以通过 JavaScript 监听 click 事件来实现相应的交互逻辑。 <!DOCTYPE html> <html> <head><meta charset"utf-8"><…

vmware16安装centos9stream

此次下载的是centos9 stream &#xff0c;使用vmware16。因为centos9stream版本比较新&#xff0c;所以vmware16无法识别此系统&#xff0c;不过无伤大雅。但是可能会导致兼容性问题&#xff0c;比如开机关机会很慢&#xff0c;建议还是用vmware17&#xff01; 下载镜像文件&a…

什么是MongoDB

概念&#xff1a; MongoDB 是一个文档数据库&#xff08;以 JSON 为数据模型&#xff09;&#xff0c;由 C 语言编写&#xff0c;旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中…

vue3-列表渲染

v-for 我们可以使用 v-for 指令基于一个数组来渲染一个列表。 v-for 指令的值需要使用 (item in items) 形式的特殊语法&#xff0c;其中 items 是源数据的数组&#xff0c;而 item 是迭代项的别名&#xff0c; (item, index) in items index 表示当前项的位置索引(可选参数)…

MySQL-多表联合查询

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

自带操作屏幕,还有AI附体的耳夹式耳机,Sanag塞那S5 Pro体验

如今耳机已经成为了我们生活中不可或缺的存在&#xff0c;很多朋友都喜欢那种能让自己获得身临其境的听觉体验的耳机。但是&#xff0c;传统的入耳式耳机常常会导致耳朵不适&#xff0c;而且特别不适合在户外使用。我最近发现了一款设计很特殊的耳机&#xff0c;就是这副sanag塞…

部署Tomcat

Tomcat简介 名称由来&#xff1a;Tomcat最初是由 Sun的软件构架师詹姆斯邓肯戴维森开发的&#xff0c;后来他帮助将其变 为开源项目&#xff0c;并由Sun贡献给Apache软件基金会&#xff0c;由于大部分开源项目OReilly都会出一本相关的 书&#xff0c;并且将其封面设计成某个动物…
最新文章