异想天开

What's the true meaning of light, Could you tell me why

C++异常

日期:2015-07-10 15:42:15
  
最后更新日期:2015-07-13 17:15:06
C++异常不是类似SIGSEG等严重错误,可以理解为一种可恢复的错误,软件层面上容错的处理。比如一个实现除法的函数,除数为0,那么这个时候可以抛出一个异常,告知调用者除数为0的异常。异常的默认处理是终止程序。
[code lang="cpp"]
#include<unistd.h>
#include<stdio.h>
#include<iostream>
using namespace std;

int foo(int a, int b) throw (const char *,int ) {
if (b == 0){
throw "Zerodivid";
}
if (b == 1){
throw -1;
}
return a/b;
}

int main()
{
try {
//foo(1,0);
foo(2,1);
} catch ( const char *a ){
std::cerr<<a<<std::endl;
} catch ( int a){
std::cerr<<a<<std::endl;
}
return 0;
}
[/code]
C++的机制是,若没有在函数申明上面指定抛出的异常,那么可以抛出任何异常。若不需要抛出任何异常,可以:
[code lang="cpp"]
int foo(int a,int b) throw(){
...
}
[/code]
throw显示抛出的异常,可以任何内置类型和自定义类型。
异常安全的级别?
异常安全等级分为基本保证,强保证和不可以抛出异常。异常安全需要做到两点:不泄漏任何资源和不允许数据败坏。不泄漏资源是必须的,对于数据破坏,基本保证意味着如果异常被抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。然而程序的现实状态(exact state)恐怕不可预料,程序有可能处于任何状态,只要那是个合法状态。强保证意味着调用这个函数,只有成功,要么不成功,不成功则状态回滚到调用之前的状态,相当于什么事也没有发生一样。而不抛出异常,意味着你这个函数要作为实现其他异常安全函数的基石,这个函数一定会正确得到执行。
《effective c++》一书对此有讲解。

析构函数与异常
栈展开(stack unwinding)过程中,会经常执行析构函数,如果析构函数发生异常,将会导致调用标准库的terminate函数,terminate函数调用abort,强制整个程序退出。析构函数做任何可能导致异常的事都是非常糟糕的主意。

未捕获的异常?
不能不处理异常,异常是足够重要,使程序不能执行的事件。如果找不到匹配的catch,程序就调用库函数terminate。

查找匹配的处理代码?
异常与catch异常说明符的匹配的规则比匹配实参和形参类型的规则更严格,大多数转换都不准许,除了下面几种以为,需要完全匹配:
1.非const到const的转换
2.派生类到基类的转换
3.数组转换为数组类型的指针
其他类型如标准算术转换和类类型定义的转换都不允许

重新抛出异常?
若在catch子句捕获到异常,进行某些处理后,还可以继续交给上层catch处理。此时,只需要空语句的throw。
[code lang="cpp"]
throw;
[/code]

异常与构造函数?
构造函数的初始化列表捕获异常,这样书写:
[code lang="cpp"]
foo::foo(void *p)
try: ptr(p),use(new size_t(1))
{
//...
} catch (const std::bad_alloc &e){
handle_out_of_memory(e);
}
[/code]