构造函数和析构函数

对于一个类

class BaseClass

{

public:

    BaseClass(char*, int);

    ~BaseClass();

private:

    char* pstring;   // 使用灵巧指针可能更好些

    int number;

};

BaseClass::BaseClass(char* p, int num) : pstring(p), number(num)

{}

BaseClass::~BaseClass()

{

    delete pstring;   // 如果使用灵巧指针这里不需要

}

构造函数一般是在生成时期进行一些必要的初始化工作,析构函数则是在其生存周期结束后进行一些扫尾任务。

对于使用成员初始化列表进行初始化的构造函数(只要可能,这也是被鼓励的方式),其成员初始化列表中的成员顺序应该与类声明中的顺序保持一致,原因在于初始化的顺序是按照类声明中的顺序进行的,如果不是按照类声明中成员顺序进行初始化,很可能产生一些你不希望发生,且难以进行错误定位的问题。

在该类中,我们使用了普通指针,而不是灵巧指针,事实上这有可能给我们制造很多令人头疼的麻烦,解决的一个比较好的办事是通过灵巧指针予以替代。类似于这种用法:

auto_ptr<char> pstring;

构造函数即变更为:

BaseClass::BaseClass(auto_ptr<char> p, int num) : pstring(p), number(num)

{}

析构函数变更为:

BaseClass::~BaseClass()

{

// 原来的代码没有了:)

}

 

析构函数需要在对象生存周期结束前进行扫尾工作,在设计析构函数的过程中应该避免(更准确的说是禁止)异常传递到析构函数外部。

析构函数在两种情况下被调用,一是正常删除对象,如生存周期结束前,调用delete operator 删除等。第二种情况是异常传递的堆栈展开(stack-unwinding)过程中,由异常处理系统删除一个对象。

调用析构函数时,异常可能被激活,也可能未被激活,因为我们无法判断,所以析构函数必须被假设在异常被激活的状态下编写。

如果一个异常被激活的同时,析构函数也抛出异常,并导致程序的控制权转移到析构函数外部,C++将调用terminate函数。它终止程序的运行,立即终止,甚至连局部对象都没有释放。!!!

例如对某类的析构函数:

SomeClass::~SomeClass()

{

    std::cout << “destructor is called !”;

}

如果在异常处于激活状态时,该析构函数抛出一个异常,因为异常未在析构函数内部进行捕获,所以被传到外部,terminate被调用,不论你希望与否,程序被粗暴的终止了!即使事态并未如此严重。

解决这种问题的一种方法就是将可能抛出异常的部分放在try{}中,用catch(…){}捕获,这可以防止异常传到外部。

第二个不允许异常传到析构函数外部的原因是:如果一个异常被析构函数抛出而未被在内部进行捕获,那么析构函数无法完全运行(异常处理机制就是这么规定的,不论你喜欢与否),而如果析构函数无法完全执行,很可能无法完成你希望完成的所有事情,你应该避免这些事情的发生。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值