C++异常处理

http://blog.csdn.net/daheiantian/article/details/6530318

异常的基本语法

1. 抛出和捕获异常

        很简单,抛出异常用throw,捕获用try……catch

        捕获异常时的注意事项:

             1. catch子句中的异常说明符必须是完全类型,不可以为前置声明,因为你的异常处理中常常要访问异常类的成员。例外:只有你的catch子句使用指针或者引用接收参数,并且在catch子句内你不访问异常类的成员,那么你的catch子句的异常说明符才可以是前置声明的类型。

             2. catch的匹配过程是找最先匹配的,不是最佳匹配。

             3. catch的匹配过程中,对类型的要求比较严格允许标准算术转换类类型的转换。(类类型的转化包括种:通过构造函数的隐式类型转化和通过转化操作符的类型转化)。

             4. 和函数参数相同的地方有: 
                    ① 如果catch中使用基类对象接收子类对象,那么会造成子类对象分隔slice)为父类子对象(通过调用父类的复制构造函数); 
                    ② 如果catch中使用基类对象的引用接受子类对象,那么对虚成员的访问时,会发生动态绑定,即会多态调用。 
                    ③ 如果catch中使用基类对象的指针,那么一定要保证throw语句也要抛出指针类型,并且该指针所指向的对象,在catch语句执行是还存在(通常是动态分配的对象指针)。

             5. 和函数参数不同的地方有:   
                     如果throw中抛出一个对象,那么无论是catch中使用什么接收(基类对象、引用、指针或者子类对象、引用、指针),在传递到catch之前,编译器都会另外构造一个对象的副本。也就是说,如果你以一个throw语句中抛出一个对象类型,在catch处通过也是通过一个对象接收,那么该对象经历了两次复制,即调用了两次复制构造函数。一次是在throw时,将“抛出到对象”复制到一个“临时对象”(这一步是必须的),然后是因为catch处使用对象接收,那么需要再从“临时对象”复制到“catch的形参变量”中; 如果你在catch中使用“引用”来接收参数,那么不需要第二次复制,即形参的引用指向临时变量。 
                    ② 该对象的类型与throw语句中体现的静态类型相同。也就是说,如果你在throw语句中抛出一个指向子类对象的父类引用,那么会发生分割现象,即只有子类对象中的父类部分会被抛出,抛出对象的类型也是父类类型。(从实现上讲,是因为复制到“临时对象”的时候,使用的是throw语句中类型的(这里是父类的)复制构造函数)。 
                    ③ 不可以进行标准算术转换类的自定义转换:在函数参数匹配的过程中,可以进行很多的类型转换。但是在异常匹配的过程中,转换的规则要严厉。

                    ④ 异常处理机制的匹配过程是寻找最先匹配(first fit),函数调用的过程是寻找最佳匹配(best fit)。

在C++中如果你throw语句中抛出一个对象,那么你抛出的对象必须要是能够复制的。因为要进行复制副本传递,这是语言的要求。

 异常重新抛出

        语法:使用一个空的throw语句。即写成: throw;   

        注意问题:

                ① throw;  语句出现的位置,只能是catch子句中或者是catch子句调用的函数中。 
                重新抛出的是原来的异常对象,即上面提到的“临时变量”,不是catch形参对象。 
                ③ 如果希望在重新抛出之前修改异常对象,那么应该在catch中使用引用参数
如果使用对象接收的话,那么修改异常对象以后,不能通过“throw;”来传播修改的异常对象,因为重新抛出不是catch形参,应该使用的是 throw e;  这里“e”为catch语句中接收的对象参数。

 捕获所有异常(匹配任何异常)

        语法:在catch语句中,使用三个点(…)。即写成:catch (…)   这里三个点是“通配符”,类似 可变长形式参数。

        常见用法:与“重新抛出”表达式一起使用,在catch中完成部分工作,然后重新抛出异常。

posted @ 2012-12-14 23:47  我不是geek  阅读(484)  评论(0编辑  收藏  举报