一、异常学习笔记
1.函数B可能抛出多种异常的处理方法
a.函数A中可有多个catch分支。catch分支中,对于异常对象,先捕获派生类对象,再捕获基类对象,按此顺序排放代码. 因为派生类对象可以隐式转换为基类对象,若想分别处理基类和派生类对象,应该将派生类对象的处理放在前面。
b.未能捕获的异常,将继续抛给上一层的调用者.
2.函数B可以声明其可能会抛出哪些异常
void B(void) thow (int, double, MyException) ... //会抛出int,double,MyException类异常,只能扔出这些异常,扔出的其它异常称为意外异常。 void B(void) thow () ... //不会会抛出任何异常 void B(void) ... //可能抛出任何异常(没有声明异常列表)
3.如果抛出了意外异常(抛出的异常不在异常列表中)可以使用set_unexpected()事先设置意外异常的处理函数(默认的异常处理函数是中止进程
的执行)。一旦出现意外异常程序一定会abort的,无论unexpected和terminate是否被设置了。
4.对于意料之外的异常,会执行2个函数:"unexpected"函数(可以自己提供),"terminate"函数(可以自己提供),设置方法如下:
#include <exception> void my_unexpected_func () { cout<<"catch my unexpected exception"<<endl; } void my_terminate_func () { cout<<"my terminate func"<<endl; } set_terminate(my_terminate_func); set_unexpected(my_unexpected_func);
其中:"unexpected"函数用来处理声明之外的异常; "terminate"函数用来处理"catch分支未捉到异常"
5.C语言中可以设置长跳转来处理异常
A(): setjmp
B(): longjmp
6.可能发出异常的代码放在try语句块中,处理异常的代码放在catch语句块中。
7.一旦发生异常(主动throw异常也是一样)就会中断当前的执行,直接跳到catch中执行。
8.catch(int i) 表示只能捕捉int类型的异常(int也是一个对象类型)。可以有多个catch()指令并列执行。一般catch(...) 用于放在最后捕捉所有其它的异常。
9.可以throw某个类的实例化对象。
10.在定义函数时就声明会扔出哪些异常,如下,此时此函数中只能扔出int或double异常,若扔出了异常列表外的其它异常会导致程序崩溃!不在异常列表中的异常称为预料之外的异常,即使在上层函数中编写了预料之外的异常的捕获代码也是捕获不到的,这些异常会继续向上抛出直到被系统默认的异常处理函数处理,默认处理函数就是把程序中止掉(自己可以设置,但是改变不了程序死掉的命运)。
void C(int i) throw(int, double) {
......
}
二、例子
#include <iostream> #include <exception> using namespace std; class MyException { public: void what() { cout << "I am MyException" << endl; } }; void my_unexpected_func () { cout<<"catch my unexpected exception"<<endl; } void my_terminate_func () { cout<<"my terminate func"<<endl; } int exception_create(char e) throw (int, char, MyException) { int int_e; char char_e; float float_e; if (e == '1') { throw int_e; } else if (e == '2'){ throw char_e; } else if (e == '3'){ throw MyException(); } else if (e == '4') { throw float_e; } cout << "exception_create finished!" << endl; return 0; } int main(int argc, char *argv[]) { if (argc != 2) { cout << "argc != 2" << endl; return -1; } char c = *argv[1]; set_terminate(my_terminate_func); set_unexpected(my_unexpected_func); try { exception_create(c); } catch(int e) { cout << "catch int_e" << endl; } catch(char e) { cout << "catch char_e" << endl; } catch(MyException &e) { cout << "catch MyException" << endl; e.what(); } catch(...) { cout << "catch catch(...)" << endl; } return 0; }