赞
踩
当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。此时,检测出问题的部分应该发出某种信号以表明程序遇到了故障,无法继续下去了,而且信号的发出方无须知道故障将在何处得到解决。一旦发出异常信号,检测出问题的部分也就完成了任务。
如果程序中含有可能引发异常的代码,那么通常也会有专门的代码处理问题。例如,如果程序的问题是输入无效,则异常处理部分可能会要求用户重新输入正确的数据;如果丢失了数据库连接,会发出报警信息。
异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。在C++语言中,异常处理包括:
程序的异常检测部分使用throw表达式引发一个异常。
语法:
throw 错误的类型(例如:runtime_error)(构造函数);
举个例子:
#include<iostream> #include<string> using namespace std; int main() { int item1, item2; cin >> item1 >> item2; if (item1==item2) { throw runtime_error("Datas aren't same!"); } else { cout << item1 + item2; } return 0; }
在这段代码中,如果两个item一样就抛出一个异常,该异常是类型runtime_error 的对象。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码。
类型runtime_ error 是标准库异常类型的一种,定义在stdexcept头文件中。我们必须初始化runtime_ error 的对象,方式是给它提供一个string对象或者一个C风格的字符串,这个字符串中有一些关于异常的辅助信息。
try 语句的基本格式:
try{
program-statement
}catch(exception-declaration){
handler-statements
}catch(exception-declaration){
handler-statements
}
······
try语句块的一开始是关键字try,随后紧跟着一个块,这个块就像大多数时候那样是花括号括起来的语句序列。
跟在try 块之后的是一个或多个catch 子句。catch子句包括三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明,exception declaration)以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。
try语句块中的program-statements 组成程序的正常逻辑,像其他任何块一样,program-statements可以有包括声明在内的任意C++语句。一如往常,try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。
#include<iostream> #include<string> using namespace std; int main() { int item1, item2; cin >> item1 >> item2; if (item1==item2) { try { throw runtime_error("Data must refer to same ISBN");//1 } catch (runtime_error err)//2 { cout << err.what();//3 } } else { cout << item1 + item2; } return 0; }
这里有三个值得注意的点:
在复杂系统中,程序在遇到抛出异常的代码前,其执行路径可能已经经过了多个try语句块。例如,一个try语句块可能调用了包含另一个try语句块的函数,新的try语句块可能调用了包含又一个try语句块的新函数,以此类推。
寻找处理代码的过程与函数调用链刚好相反。当异常被抛出时,首先搜索抛出该异常的函数。如果没找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch 子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。如果最终还是没能找到任何匹配的catch子句,程序转到名为terminate 的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。对于那些没有任何try语句块定义的异常,也按照类似的方式处理:毕竟,没有try语句块也就意味着没有匹配的catch子句。如果一段程序没有 try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。(这一段好好进行理解)
但是实际上这个函数用不到,我们只要未进行定义的异常,都会自动进行退出。
例子:
#include<iostream> #include<string> using namespace std; int main() { int item1, item2; cin >> item1 >> item2; if (item1==item2) { try { throw runtime_error("Data must refer to same ISBN"); } catch (runtime_error err) { cout << err.what(); terminate(); } } else { cout << item1 + item2; } return 0; }
输出结果:
C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用,它们分别定义在4个头文件中:
错误 | 描述 |
---|---|
exception | 最常见的问题 |
runtime_error | 只有运行的时候才能检测出的问题 |
range_error | 运行时错误:生成的结果超过了有意义的值域范围 |
overflow_error | 运行时错误:计算上溢 |
underflow_error | 运行时错误:计算下溢 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误:参数对应的结果值不存在 |
invalid_argument | 逻辑错误,无效参数 |
length_error | 逻辑错误:试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误:使用一个超出有效范围的值 |
但如果要自己写try的话我们都写runtime_error即可。剩下的自己理解一下,后面自己敲代码的时候出现这些错误,知道是什么错误即可。
what函数返回的字符串内容和异常处理对象的类型有关。如果异常处理类型有一个字符串初始值,则what返回该字符串。对于其他无初始值的异常类型来说,what返回的内容由编译器决定。
最后给一段代码大家理解一下:
#include<iostream> #include<string> using namespace std; int main() { int item1, item2; cin >> item1 >> item2; if (item2==0) { try { throw runtime_error("除数不能为0"); } catch (runtime_error err) { cout << err.what()<<endl<< "try again!"<<endl; cin >> item1 >> item2; } } cout << item1 / item2; return 0; }
输出结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。