异常、虚函数与构造函数、析构函数

本文详细解析了 C++ 中的异常处理机制,包括栈展开过程、析构函数调用时机及其注意事项,并探讨了虚函数在析构函数中的应用及限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一。异常

1.栈展开(stack unwinding):

    异常抛出的时候,将暂停当前函数的执行,开始查找匹配的catch字句。

    首先检查throw语句是否在当前函数的try语句中,如果是,而且有相应的catch语句与抛出对象相匹配,则就处理异常;如果没有在try语句中,或没有相匹配的catch语句,则就会退出当前函数(释放当前函数的内存、撤销局部对象);

 然后再在调用函数中查找,即查看抛出异常的函数是否在调用函数中的try语句中,如果是且有相应的catch语句与抛出的对象匹配,则就处理异常;如果没有在try语句中, 或没有相匹配的catch语句,则会推出该调用函数;

    然后再在上一层的调用函数中查找...

    直到找到一个跟该异常相匹配的catch语句为止,则其处理该异常;如果异常没有被任何一个catch语句匹配,也即是不能被处理,则C++会调用terminate函数,结束整个程序。

 

2.析构函数:

   析构函数被调用的情况有两种:

    一是正常情况下删除或释放一个完全构造的对象,比如对象超出了作用域或被delete;

    二是异常被抛出和传递的过程中,栈展开机制撤销一个完全构造的对象。

     注意:栈展开机制只能撤销局部对象,即调用完全构造的局部对象的析构函数来释放对象;而不能也不会释放局部指针指向的动态堆内存。

 

3.绝对不能让异常逃出析构函数之外:

   也即是如果析构函数有可能抛出异常,则必须在析构函数内消化处理所有可能的异常,原因有二:

   析构函数不能完全执行析构函数,这可能会导致内存泄露;

   如果一个析构函数是在异常传递的栈展开过程中被调用,而且它也抛出一个异常逃出析构函数,则会引发严重的后果:C++调用terminate函数,整个程序会立即结束,甚至来不及释放局部对象。

 

4.对象的完全构造:

   当且仅当构造函数完全执行时,这个对象才是完全构造的对象;

   C++仅能删除完全构造的对象。

 

5.异常可以逃出构造函数之外:

    异常可以逃出构造函数之外,但是如果这种情况下不会调用这个未完全构造对象的析构函数;

    而只是栈展开机制会释放局部对象(即调用成员变量的析构函数),而不会释放指针指向的堆内存,因此需要用对象管理资源。

 

二。虚函数

1.虚函数与析构函数:

   具有多态性质的基类的析构函数必须是虚函数,这是因为:

   如果基类的指针或引用指向或引用派生类对象时,当通过该指针或引用释放该对象时,则只会使用基类的析构函数,释放掉基类的部分。

 

   但是析构函数中尽量不要调用虚函数,这是因为:

   一旦开始调用派生类析构函数,则派生类的数据成员变得无定义;进入基类的析构函数后,对象便成为了一个基类对象了。

 

2.”虚“构造函数:

    没有虚构造函数。

    构造函数中也尽量不要调用虚函数,这是因为:

    在派生类对象的构造函数执行之前,先执行基类的构造函数,在此期间对象的类型是基类类型。

       

  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值