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


    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

  • 相关阅读:
    Android Studio 单刷《第一行代码》系列 05 —— Fragment 基础
    Android Studio 单刷《第一行代码》系列 04 —— Activity 相关
    Android Studio 单刷《第一行代码》系列 03 —— Activity 基础
    Android Studio 单刷《第一行代码》系列 02 —— 日志工具 LogCat
    Android Studio 单刷《第一行代码》系列 01 —— 第一战 HelloWorld
    IDEA 内网手动添加oracle,mysql等数据源,以及server returns invalid timezone错误配置
    eclipse maven设置
    IntelliJ IDE 常用配置
    eclipse maven 常见问题解决方案
    Maven 安装和配置
  • 原文地址:https://www.cnblogs.com/rogerroddick/p/2966779.html
Copyright © 2020-2023  润新知