• 第27课 二阶构造模式(构造函数二阶构造)


    1. 构造函数的回顾

    (1)关于构造函数

      ①类的构造函数用于对象的初始化

      ②构造函数类同名并且没有返回值(思考:无返回值如何判断构造函数的执行结果?)

      ③构造函数对象定义自动被调用

    (2)构造函数的真相

      ①构造函数只提供自动初始化成员变量的机会,但不能保证初始化逻辑一定成功它只能决定对象的初始状态,而不是对象的诞生

      ②构造函数执行return语句后,构造函数立即结束

    【编程实验】异常的构造函数   27-1.cpp

    #include <stdio.h>
    
     
    
    class Test
    
    {
    
    private:
    
        int mi;
    
        int mj;
    
        bool mStatus;
    
     
    
    public:
    
        Test(int i, int j):mStatus(false)
    
        {
    
            mi = i;
    
     
    
            return;//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()) //构造未完成,status为false
    
        {
    
            printf("t1.mi = %d
    ", t1.getI());//i被正确初始化
    
            printf("t1.mj = %d
    ", t1.getJ());//j为随机值
    
        }
    
     
    
        return 0;
    
    }

    运行结果:

      

    2. 半成品对象

    (1)初始化操作不能按照预期完成得到的对象

    (2)半成品对象合法C++对象也是bug的重要来源

    3. 二阶构造

    (1)工程开发中的构造过程

      ①资源无关的初始化操作阶段不会出现异常情况的操作

      ②需要使用系统资源的操作可能出现异常,如内存申请,访问文件等。

            

    (2)二阶构造示例

    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;
    }

    【编程实验】二阶构造初探  27-2.cpp

    #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;
    
    }

    【编程实验】数组类的加强   IntArray

    //IntArray.h

    #ifndef _INTARRAY_H_
    
    #define _INTARRAY_H_
    
     
    
    class IntArray
    
    {
    
    private:
    
        int m_length;
    
        int* m_pointer;
    
     
    
        //将构造函数变为私有的
    
        IntArray(int len);
    
        bool construct(); //第2阶构造函数
    
     
    
    public:
    
        static IntArray* NewInstance(int length);//提供创建对象的函数
    
        int length();
    
        bool get(int index, int& value);
    
        bool set(int index, int value);
    
        ~IntArray();
    
    };
    
     
    
    #endif

    //IntArray.cpp

    #include "IntArray.h"
    
     
    
    IntArray::IntArray(int len)
    
    {
    
        m_length = len;
    
    }
    
     
    
    bool IntArray::construct()
    
    {
    
        bool ret = true;
    
     
    
        m_pointer = new int[m_length];
    
     
    
        if (m_pointer)
    
        {
    
            for(int i = 0; i<m_length; i++)
    
            {
    
                m_pointer[i] = 0;
    
            } 
    
        }
    
        else
    
        {
    
            ret = false;
    
        }
    
       
    
        return ret;
    
    }
    
     
    
    IntArray* IntArray::NewInstance(int length)
    
    {
    
        IntArray* ret = new IntArray(length);
    
     
    
        if(!(ret && ret->construct()))
    
        {
    
            delete ret;
    
            ret = 0;
    
        }
    
     
    
        return ret;
    
    }
    
     
    
    IntArray::~IntArray()
    
    {
    
        if(m_pointer)
    
        {
    
            delete[] m_pointer;
    
        }
    
    }
    
     
    
    int IntArray::length()
    
    {
    
        return m_length;
    
    }
    
     
    
    bool IntArray::get(int index, int& value)
    
    {
    
       bool bRet = (0 <= index) && (index <m_length);
    
     
    
       if(bRet)
    
       {
    
            value = m_pointer[index];
    
       }
    
     
    
       return bRet;
    
    }
    
     
    
    bool IntArray::set(int index, int value)
    
    {
    
     
    
       bool bRet = (0 <= index) && (index <m_length);
    
     
    
       if(bRet)
    
       {
    
            m_pointer[index] = value;
    
       }
    
     
    
       return bRet;
    
    }

    //main.cpp

    #include <stdio.h>
    
    #include "IntArray.h"
    
     
    
    int main()
    
    {
    
        IntArray* a = IntArray::NewInstance(5);
    
     
    
        printf("a.length = %d
    ", a->length());
    
     
    
        a->set(0, 1);
    
     
    
        for(int i = 0; i< a->length(); i++)
    
        {
    
            int v = 0;
    
     
    
            a->get(i, v);
    
     
    
            printf("a[%d] = %d
    ", i, v);
    
        }
    
     
    
        delete a;
    
     
    
        return 0;
    
    }

    4. 小结

    (1)构造函数只能决定对象初始化状态

    (2)构造函数初始化操作的失败不影响对象的诞生

    (3)初始化不完全半成品对象bug的重要来源

    (4)二阶构造人为的将初始化过程分为两个部分

    (5)二阶构造能够确保创建的对象都是完整初始化的

  • 相关阅读:
    composer使用git作为仓储
    monolog记录日志
    lumen laravel response对象返回数据
    lumen中间件 Middleware
    AcWing 901. 滑雪
    leetcode 34. 在排序数组中查找元素的第一个和最后一个位置
    acwing 902. 最短编辑距离
    ACWING 844. 走迷宫
    leetcode 5199. 交换字符串中的元素
    AcWing 836. 合并集合
  • 原文地址:https://www.cnblogs.com/hoiday/p/10092183.html
Copyright © 2020-2023  润新知