C++的异常处理

  看了一些Thinking in C++ v2中的异常的内容,做了一些总结,分享如下:

在C++中,异常处理(Exception Handle)主要还是try,throw和catch的用法,最简单的用法是这样的:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6 try
 7 {
 8    throw 1 ;
 9 }catch(int)
10 {
11    cout<<"catch int "<<endl ;
12 }
13 return 0 ;
14 }

  正如Fatmouse所说,Exception相当于一个地方着火了,throw相当于扔出了东西让人知道发生了什么,被抛出去的东西可以 是任何东西,可以是整形,字符,也可以是自己建的一

个类。尽管如此,起码扔出去的东西能让人知道发生了什么,而catch的语法是catch(type id),其是相当于一个变量的定义,如果id用不到也可以省略,就像第一个例子,catch的只是一个类型。
另外一个例子:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6 try
 7 {
 8    throw 1 ;
 9 }catch(int)
10 {
11    cout<<"catch int "<<endl ;
12 }
13 return 0 ;
14 }


在这里,输出是 begin try begin f() in catch 也就是说,一旦一个异常被抛出以后这个函数就结束了,一个try block也结束了。 异常的匹配有几个原则 1,异常被抛出以后会逐个匹配,知道匹配到第一个匹配为止,如果一层的catch没有catch到,就跳到外层的try block去寻找匹配,知道找到为止。 2,如果一个异常是自己建的对象那么子类的异常可以被catch父类的catch语句catch到。 3,在异常的匹配的时候不能进行自动类型转换。 4,catch(...)可以catch到任何异常。 这里有一个疑问,要是一个异常没有被catch到的话会发生什么事情?结果是,一个函数terminate()会被自动调用,程序就终止了。在本地对象的 析构函数抛出异常的时候或者全

局或静态对象的构造或析构函数中抛出异常的时候也会自动调用terminate()函数,默认情况下调用的是abort()函数,也可以自己来设 置,用set_terminate()函数,自己定义一个

void f(){...},然后set_terminate(f);就可以了。以上两个函数在<exception>中。
一个内存泄露的问题,书上有下面这个例子:

这里Cat()被调用过了三次,但是~Cat()却没有被调用,解决方法是讲内存申请放在构造函数里面,内存释放放在析构函数里面,在C++库中有 这样一个类,叫做auto_ptr就是可以

避免这样的内存泄露的,这个auto_ptr也是一个模版,用法是auto_ptr<Cat>,这个类放 在<memory>中。
try还有一个用法叫做function-level try blocks,用在整个函数的异常处理中,如:
void f() try
{
throw 1 ;
}catch(int)
{
cout<<"function catch"<<endl ;
}

标准异常
C++库中给出了一些标准异常,最高的是exception类,它派生出去的有logic_error 和runtime_error两个类。logic_error派生出去的有domain_error、invalid_error、

length_error、out_of_range、bad_typeid等类。runtime_error派生出去的有 range_error、overflow_error、bad_alloc等类。
异常的指定
如果要规定一个函数只能抛出几个类型的异常,可以用throw语句来指定,用法如下void f() throw(A,B,C);就是说只能抛出A,B,C这三种类型的异常,其它异常不能抛出,那么抛

出其它异常会怎么样呢?答案是调用了unexpected函数,默认的unexpected调用的是terminate函数,如果要对 unexpected函数进行设置,可以使用set_unexpected进行设置,用法

和set_terminate一样,以上两个函数也在<exception>中,也在<exception>中有一个异常 类叫做bad_expection,这个类可以用以接受抛出的没有在列表中的异常,例如:
void f() throw(A,bad_exception){throw B ;}那么抛出的异常就变为bad_exception了,如果没有bad_exception,unexpected()被调用。
另外要注意的是,抛出的异常类最好用引用。

posted on 2010-02-05 01:43  vivy  阅读(474)  评论(0编辑  收藏  举报