异常的构造函数、二阶构造模式

目录

异常的构造函数

构造与析构中的异常

二阶构造模式 


异常的构造函数

面试题 1

1. 如何判断构造函数的执行结果? 

2. 在构造函数中执行return语句会发生什么? 

3. 构造函数执行结束是否意味着对象构造成功?

      ① 没有办法直接判断构造函数的执行结果,不过可以设置一个状态变量放在构造函数末尾

      ② return语句执行后,构造函数立即返回(return前面初始化成功,后面部分未初始化为随机值)

      ③ 构造函数执行结束,且并不意味着对象构造成功

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

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

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

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

                    

 

构造与析构中的异常

面试题 2

如果构造函数中抛出异常会发生什么情况?析构抛出异常呢?

构造过程立即停止,当前对象无法生成,析构函数不会被调用,对象所占用的空间立即收回

避免在析构函数中抛出异常, 析构函数的异常将导致对象所使用的资源无法完全释放

工程项目中的建议 

避免在构造函数中抛出异常 ,当构造函数可能产生异常时,使用二阶构造模式 (二阶构造模式是唐老师总结的一种可行的设计模式,非常实用)

#include <iostream>  
  
using namespace std;  
  
class Test  
{  
public:  
    Test()  
    {  
        cout << "Test()" << endl;  
          
        throw 0;  
    }  
    virtual ~Test()  
    {  
        cout << "~Test()" << endl;  
    }  
};  
  
  
int main(int argc, char *argv[])  
{  
    Test* p = reinterpret_cast<Test*>(1);  
      
    try  
    {  
        p = new Test();  // 异常,对象构造失败,内存回收
    }  
    catch(...)  
    {  
        cout << "Exception..." << endl;  
    }  
      
    cout << "p = " << p << endl;  
      
    return 0;  
}  

使用valgrind检测发现没有产生内存泄漏 

 

二阶构造模式 

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

  -资源无关的初始化操作 :不可能出现异常情况的操作 

  -需要使用系统资源的操作 :可能出现异常情况,如:内存申请,访问文件 ...

    

二阶构造示例

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

编程实验 : 数组类

IntArray.h

#ifndef _INTARRAY_H_  
#define _INTARRAY_H_  
  
class IntArray  
{  
private:  
    int m_length;  
    int* m_pointer;  
      
    IntArray(int len);  
    IntArray(const IntArray& obj);  
    bool construct();  
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;  
}  
  
int IntArray::length()  
{  
    return m_length;  
}  
  
bool IntArray::get(int index, int& value)  
{  
    bool ret = (0 <= index) && (index < length());  
      
    if( ret )  
    {  
        value = m_pointer[index];  
    }  
      
    return ret;  
}  
  
bool IntArray::set(int index, int value)  
{  
    bool ret = (0 <= index) && (index < length());  
      
    if( ret )  
    {  
        m_pointer[index] = value;  
    }  
      
    return ret;  
}  
  
IntArray::~IntArray()  
{  
    delete[]m_pointer;  
}

main.cpp 

#include <stdio.h>  
#include "IntArray.h"  
  
int main()  
{  
    IntArray* a = IntArray::NewInstance(5);      
      
    printf("a.length = %d\n", 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\n", i, v);  
    }  
      
    delete a;  
      
    return 0;  
} 

                    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值