C++异常基础

最近在看C++编程规范和C++primer,遇到了有关异常的一些内容,在此简单总结一下,以后可能会继续补充


1.异常的意义是什么?为什么要进行异常处理?

异常机制允许我们在运行时就对出现的问题进行及时处理,假如我们的程序运行过程出现错误,我们又不想让程序直接挂掉,我们就可以对可能出现的错误提前进行处理。

异常机制使我们能将问题的检测与解决过程分开,模块化设计是大家所提倡的,既然我们决定要对错误进行处理,就要写处理的逻辑代码,如果和业务逻辑写在一起会使代码非常凌乱,不利阅读和移植。


2.抛出异常和捕获异常时发生了什么?

当我们抛出一个异常时,程序就暂停在当前的执行并开始寻找与异常匹配的catch子句。

首先,当throw在一个try语句块中时,就先检查与该块关联的catch语句。如果找到就使用这个catch来处理,如果找不到并且这个try被嵌套到其他的语句块,那么就继续检查外层的catch语句,如果还是找不到,就退出当前的函数,在调用当前函数的外层函数中找,如下图。

同理如果一个异常来源一个位于try语句块中的语句,那么也是上面的嵌套调用过程。

这个过程被叫做栈展开,如果最后都没有找到匹配的catch就会调用terminate函数终止程序。

3.异常对象是什么?与其他对象有什么不同?

异常对象是一种特殊的对象,编译器使用异常抛出表达式来对异常对象进行初始化。

异常对象由于其机制的特别,位于由编译器管理的空间中。那么为什么这么做?根据我们刚才提到的栈展开规则,如果在当前catch找不到匹配的异常,就要退出当前的语句块,与此同时,这个语句块的所有局部对象就会被释放掉。如果我们抛出的是一个指向局部对象的指针,那个指针指向的就是一个被释放的内存,这肯定是错误的。

所以由编译器来创造一个特殊的空间来管理异常对象,这样才能确保无论程序调用的是哪个catch子句都能访问该空间


4.异常对象的类型由谁决定?

当我们抛出一个表达式时,catch表达式的参数的静态编译类型就决定了异常对象的类型。

 

5.catch语句里的参数为什么有时可以省略形参?

如果catch只需要了解异常的类型,就可以省去形参。但是假如我们要对异常对象进行处理就需要保留形参。其实,我们可以把catch(参数)语句看做一个函数,当进入一个catch后,异常对象被初始化,如果catch括号里面的是非引用类型,则异常对象是一个局部副本,如果是引用类型,则参数就是一个别名。


6.既然说catch语句既然和函数匹配相似,那是不是有什么不同?

虽然catch的执行有点像函数匹配,但是catch明显要严格很多。只允许3种转换匹配。

1.非常量到常量的类型转换

2.派生类到基类的转换

3.数组转换为指向数组类的指针

另外,如果catch的参数是一个基类类型,则可以用派生类类型来对其初始化,不过这时候就会发生切片简单理解就是,用子类对象对基类对象进行赋值运算时会将子类对象独有的(非继承的部分)函数和变量自动切去的机制。只留下子类继承来的基类原有的切片来对基类的对象进行赋值。

 

注意catch的执行和switch case类似,自上向下顺序执行,由于我们说道catch可以匹配一个基类类型的所有派生类类型,所以要把最专门详细的匹配放在前面,越宽泛的放在后面。

 

7.构造函数初始化列表的异常可以捕获么?有什么特别的?

任何地方都可能出现异常,包括类的构造函数初始化数据的时候,这种情况下我们无法用普通的try catch形式来捕获,我们必须要将构造写成函数try语句块。

   class TryClass 
  {  
    int* m_pArray;  
    public:  
       TryClass  ( int m_pNum );  
       ~ TryClass  ();  
   };  
   TryClass :: TryClass  ( int pNum )  
       try: pArray ( new int[pNum ] )  
     {  
       cout << pNum << endl;   
     }  
      catch ( bad_alloc& error )  
     {  
      cout << "alloc error" << endl;  
     };  

 

如果当前语句的catch不能处理或者不想处理捕获到的异常可以通过throw;来重新抛出,这个异常会被传到外层的catch中去。

如果想捕获所有异常,使用catch(...)语句即可。

 


下一篇博客给大家分析一下C++编程规范101条     C++编程规范解析 62条 不要允许异常跨越模块边界传播



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值