c++异常处理

来源:互联网 发布:js给div设置内容 编辑:程序博客网 时间:2024/06/02 05:03

异常,让一个函数可以在发现自己无法处理的错误时抛出一个异常,希望它的调用者可以直接或者间接处理这个问题。而传统错误处理技术,检查到一个局部无法处理的问题时:

1.终止程序(例如atol,atoi,输入NULL,会产生段错误,导致程序异常退出,如果没有core文件,找问题的人一定会发疯)

2.返回一个表示错误的值(很多系统函数都是这样,例如malloc,内存不足,分配失败,返回NULL指针)

3.返回一个合法值,让程序处于某种非法的状态(最坑爹的东西,有些第三方库真会这样)

4.调用一个预先准备好在出现"错误"的情况下用的函数。

第一种情况是不允许的,无条件终止程序的库无法运用到不能当机的程序里。第二种情况,比较常用,但是有时不合适,例如返回错误码是int,每个调用都要检查错误值,极不方便,也容易让程序规模加倍(但是要精确控制逻辑,我觉得这种方式不错)。第三种情况,很容易误导调用者,万一调用者没有去检查全局变量errno或者通过其他方式检查错误,那是一个灾难,而且这种方式在并发的情况下不能很好工作。至于第四种情况,本人觉得比较少用,而且回调的代码不该多出现。

使用异常,就把错误和处理分开来,由库函数抛出异常,由调用者捕获这个异常,调用者就可以知道程序函数库调用出现错误了,并去处理,而是否终止程序就把握在调用者手里了。

但是,错误的处理依然是一件很困难的事情,C++的异常机制为程序员提供了一种处理错误的方式,使程序员可以更自然的方式处理错误。

异常的描述

函数和函数可能抛出的异常集合作为函数声明的一部分是有价值的,例如

void f(int a) throw (x2,x3);

表示f()只能抛出两个异常x2,x3,以及这些类型派生的异常,但不会抛出其他异常。如果f函数违反了这个规定,抛出了x2,x3之外的异常,例如x4,那么当函数f抛出x4异常时,
会转换为一个std::unexpected()调用,默认是调用std::terminate(),通常是调用abort()。

如果函数不带异常描述,那么假定他可能抛出任何异常。例如:

int f();  //可能抛出任何异常

不带任何异常的函数可以用空表表示:

int g() throw (); // 不会抛出任何异常

捕获异常

捕获异常的代码一般如下:

try {    throw E();}catch (H h) {     //何时我们可以能到这里呢}

1.如果H和E是相同的类型

2.如果H是E的基类

3.如果H和E都是指针类型,而且1或者2对它们所引用的类型成立

4.如果H和E都是引用类型,而且1或者2对H所引用的类型成立

从原则上来说,异常在抛出时被复制,我们最后捕获的异常只是原始异常的一个副本,所以我们不应该抛出一个不允许抛出一个不允许复制的异常。

此外,我们可以在用于捕获异常的类型加上const,就像我们可以给函数加上const一样,限制我们,不能去修改捕捉到的那个异常。

还有,捕获异常时如果H和E不是引用类型或者指针类型,而且H是E的基类,那么h对象其实就是H h = E(),最后捕获的异常对象h会丢失E的附加携带信息。

 

0 0
原创粉丝点击