zoukankan      html  css  js  c++  java
  • C++解析(15):二阶构造模式

    0.目录

    1.构造函数与半成品对象

    2.二阶构造

    3.小结

    1.构造函数与半成品对象

    关于构造函数:

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

    问题:

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

    (没有办法判断构造函数的执行结果,构造函数执行结束不意味着对象构造成功)
    用一个状态来表示对象是否构造成功:

    #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
    ", t1.getI());
            printf("t1.mj = %d
    ", t1.getJ());
        }
        
        return 0;
    }
    

    输出结果为空。

    构造函数:

    • 只提供自动初始化成员变量的机会
    • 不能保证初始化逻辑一定成功
    • 执行return语句后构造函数立即结束

    构造函数能决定的只是对象的初始状态而不是对象的诞生!!

    半成品对象的概念:

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

    2.二阶构造

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

    • 资源无关的初始化操作
      1. 不可能出现异常情况的操作
    • 需要使用系统资源的操作
      1. 可能出现异常情况,如:内存申请,访问文件

    二阶构造:

    二阶构造示例一:

    二阶构造示例二:

    示例代码:

    #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
    ", 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
    ", obj);
    
        delete obj;
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    obj = (nil)
    

    会返回一个空。

    使用二阶构造模式后,对象只能在堆空间上创建,不能在栈上产生了。这恰恰是工程里面最重要的一个决定,因为在工程中,对象往往是比较巨大的,不适合放在栈空间当中,都应该放到堆空间里面去。

    3.小结

    • 构造函数只能决定对象的初始化状态
    • 构造函数中初始化操作的失败不影响对象的诞生
    • 初始化不完全的半成品对象是Bug的重要来源
    • 二阶构造人为的将初始化过程分为两部分
    • 二阶构造能够确保创建的对象都是完整初始化的
  • 相关阅读:
    如何写好 5000 行的 SQL 代码
    Oracle面对“数据倾斜列使用绑定变量”场景的解决方案
    OAuth2.0最简向导(多图预警)
    再见,2019!你好,2020!
    快过年了,来,来,来!给七大姑八大姨好好解释解释【啥是DBA 】
    linux 定期清除日志
    人工智能:才赢李世石,再“战”巴菲特
    人工智能:才赢李世石,再“战”巴菲特
    人工智能:才赢李世石,再“战”巴菲特
    人工智能:才赢李世石,再“战”巴菲特
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10082681.html
Copyright © 2011-2022 走看看