0
点赞
收藏
分享

微信扫一扫

39 C++ 模版中的参数如果 是 vector,list等集合类型如何处理呢?

目录

构造函数回顾

深入思考

实验

构造函数的真相

半成品对象

引入二阶构造设计模式

设计理念

二阶构造设计模式图

二阶构造示例

完整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. 二阶构造能够确保创建的对象都是完整初始化的。

举报

相关推荐

0 条评论