Roger Luo

超越梦想一起飞
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++ Throw exception in contructor 构造函数异常处理

Posted on 2013-03-18 21:01  Roger Luo  阅读(1431)  评论(1编辑  收藏  举报
class ComplexA
{
public:
ComplexA(int len):_l(len), _p(new char[_l]){cout<<"ComplexA::ComplexA"<<endl;}
~ComplexA(){cout<<"ComplexA::~ComplexA"<<endl; if (_p != nullptr) delete _p;}
private:
int _l;
char * _p;
};
class ComplexB
{
public:
ComplexB(int len):_l(len), _p(new char[_l]){cout<<"ComplexB::ComplexB"<<endl;}
~ComplexB(){cout<<"ComplexB::~ComplexB"<<endl; if (_p != nullptr) delete _p;}
private:
int _l;
char * _p;
};
class ComplexC
{
public:
ComplexC(int len):_l(len), _p(new char[_l]){cout<<"ComplexC::ComplexC"<<endl;}
~ComplexC(){cout<<"ComplexC::~ComplexC"<<endl; if (_p != nullptr) delete _p;}
private:
int _l;
char * _p;
};
class Wrapper
{
public:
Wrapper(int lenA, int lenB, int lenC):pA(new ComplexA(lenA)), pB(new ComplexB(lenB)), pC(new ComplexC(lenC)){cout<<"Wrapper::Wrapper"<<endl;}
~Wrapper(){cout<<"Wrapper::~Wrapper"<<endl; if (pA) delete pA; if (pB)delete pB; if (pC)delete pC;}
private:
ComplexA * pA;
ComplexB * pB;
ComplexC * pC;
};
如果在ComplexC的构造函数中跑出bad_alloc异常,将会发现之前分配的ComplexA与ComplexB将不会给释放。
但是如果将Wrapper修改成如下,不是包含复杂对象的指针而是他的实体变量,则会逆序释放部分构造成功的复杂对象:
class Wrapper2
{
    public:
        Wrapper2(int _a, int _b, int _c):
            a(_a), b(_b), c(_c)
        {

        }
    private:
        ComplexA a;
        ComplexB b;
        ComplexC c;
};
输出结果为:

ComplexA::ComplexA
ComplexB::ComplexB
ComplexC::ComplexC
ComplexB::~ComplexB
ComplexA::~ComplexA
Catch bad_alloc

构造函数中不管是在initialize list中分配,还是构造函数体中,还是会有如下结论:

构造函数中抛出异常时概括性总结
(1) C++中通知对象构造失败的唯一方法那就是在构造函数中抛出异常;
(2) 构造函数中抛出异常将导致对象的析构函数不被执行; 所以如果子对象是指针的形式将会不会释放,因为释放是在母体的析构函数中
(3) 当对象发生部分构造时,已经构造完毕的子对象将会逆序地被析构;
(4) 其是还是那句话, “C++的异常处理不会破坏任何一条面向对象的特性!”。

那么通过上面两个wrapper,是否意味复杂子对象不能用指针来存储呢,否则将会导致部分构造子对象无法释放,不过C++11出来了,智能指针可以拯救你:

修改wrapper如下:

class Wrapper3
{
    public:
        Wrapper3(int la, int lb, int lc):
            pa(make_shared<ComplexA>(la)),
            pb(make_shared<ComplexB>(lb)),
            pc(make_shared<ComplexC>(lc))
        {

        }
        ~Wrapper3(){}
    private:
        shared_ptr<ComplexA> pa;
        shared_ptr<ComplexB> pb;
        shared_ptr<ComplexC> pc;
};

main函数中

shared_ptr<Wrapper3> pw = make_shared<Wrapper3>(1,2,3);

输出结果为:

ComplexA::ComplexA
ComplexB::ComplexB
ComplexC::ComplexC
ComplexB::~ComplexB
ComplexA::~ComplexA
Catch bad_alloc