C++ 处理异常的 手段通常有一下几种
1、通过 throw 抛出异常 , 抛出的异常 将会向上寻找最近匹配 的 catch() 语句块 来处理异常 ,如果 未找到匹配的 catch , 异常将会自动调用
terminate 来终止程序的执行。 在C++中,所有未处理的异常都会 导致调用 terminate 来使程序终止
throw 可以抛出 C++ 标准库 定义的 标准异常 , 也可以抛出自定义的异常
2、通过 try{} catch(){} 语句块来处理异常
try{} 中通常存放的是 可能会发生异常的代码 , catch(异常类型){} 存放的事针对 某种异常 进行处理的代码
catch 语句的括号中存放的是 异常类型定义语句
例如
1 try{ 2 if(1){ 3 throw 1; 4 } 5 }catch(const char* err){ 6 cout<<err<<endl; 7 8 }catch(int err){ 9 cout<<err<<endl; 10 }
上述代码中 try 语句块中 throw 出了 一个 异常值 为 1 的异常 , 1 在C++编译器中的默认为 整形 。当抛出异常后 , 异常会顺着异常调用链向上查找匹配的
异常 处理 catch , 首先 catch(const char* err) {} 被找到 , 但是异常类型不匹配 , 则 pass , 继续向下找 , 找到了 catch(int err) ,这段 异常处理程
序要处理的异常类型为整形, 这就意味着 找到了匹配的catch , 程序就会跳到 该catch 中执行处理程序 , 上述代码中的处理过程只是简单的把异常的值打印出来。
注意: 就像上述示例代码 , 如果 抛出异常后 在代码当前所在的函数中找不到匹配的 的 catch , 就会顺着异常 异常调用链 到 caller function 中去找匹配的
catch , 就这样一直向上 直到找到匹配的catch 或者 遇到 catch(...) 或者 异常调用链匹配结束为止 。
catch(...) 这样的语句的作用是捕获所有类型的异常 , 通常用于 默认的 异常处理。
另外 , 关于 finally , 在 windows 平台上 C++ 代码中 可能会见到 诸如 try{}catch(xxx){}finally{} 这样的代码 , 要注意 finally 不是 C++ 关键字 ,
而只是 MS编译器对C++的扩展 , finally 的作用 和 catch(...) 的作用相同 , 都是 用于对 异常的默认处理
标准异常:
C++中定义了一组类 , 用户报告在标准库中的函数 执行的时候 遇到的问题。
这些异常类定义在一下四个头文件中
(1)、<exception> 该头文件中定义了最常见的异常类 exception 这个类智能告知有异常产生, 但是不能提供更多的信息 , catch(exception e) 等同于 catch(...) (可能)
(2)、<stdexcept> 改天头文件中定义了 几种常见的异常类
exception 最常见的异常类
runtime_error 运行时错误:仅在运行时才能检测到的错误
range_error 运行时错误,生成的结果超出了有意义的值域的范围
overflow_error 运行时错误:计算上溢
underflow_error 运行时错误:计算下溢
logic_error 逻辑错误:可在运行前检测到的错误
domain_erroe 逻辑错误:参数的结果值不存在
invalid_argument 逻辑错误:不合适的参数
length_error 逻辑错误,试图生成一个超出该类最大长度的对象
out_of_range 逻辑错误:使用一个超出有效范围的值
(3)、<new> 头文件定义了 bad_alloc 异常类型 , 提供了因无法分配内存而由new抛出的异常
(4)、<type_info> 头文件 定义了 bad_cast 异常类型 ,
exception bad_cast bad_alloc 异常类 只提供了 默认构造函数 , 所以无法再定义对象的时候给他们赋初值
其他异常类 之定义了 用string 对象来 初始化的 构造函数 , 就是说只能用一个 string 对象来初始化,该string对象用于为发生的异常提供更多的信息
异常类型 还定义了一个 what 成员函数 , 该函数 返回 const char* 类型的值 , 提示异常信息。