异常处理
- 一、简介
- 二、throw表达式
- 三、try语句块
- 四、标准异常
一、简介
什么是异常:
- 异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接以及遇到意外输入等。处理反常行为可能是设计所有系统最难的一部分。
- 异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持,异常检测主要是throw 的任务,而异常处理主要是 try语句块去执行。
=====================
在C++语言中主要为:
- throw表达式(throw expression),异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们就说throw引发了异常。
- try语句块(try block),异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个 catch子句结束。try语句块 中代码抛出的异常通常会被某个catch子句处理。因为catch子句“处理”异常,所以它们也被称作异常处理代码(exceptionhandler),
- 一套异常类(exception class),用于在throw表达式和相关的catch子句之间传递异常的具体信息 (不要求掌握) 。
我们先看一个简单的代码:
int main() { int x, y; cout << "输入两个数进行相除:" << endl; cin >> x >> y; cout << "x / y = " << x / y << endl; return 0; }
注: 当输入的两个数进行相除并且分母为0时,系统就会认为是错误,就会报错,例:
第一次是对的,第二次输入的分母为0,于是就无法计算出结果,报出一些的别的错误。
按照大多数人的编程习惯会将它的这个问题给避免,就会这样做:
int main() { int x, y; cout << "输入两个数进行相除:" << endl; cin >> x >> y; if (y == 0) { cout << "除数y不能为0." << endl; return -1; } cout << "x / y = " << x / y << endl; return 0; }
这样就不会执行到下面的语句,然而我们们接下来要介绍的是C++常用的异常处理机制。
二、throw表达式
- 程序的异常检测部分使用throw表达式引发一个异常。throw表达式包含关键字 throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型(就是下面会讲到标准异常)。throw表达式后面通常紧跟一个分号,从而构成一条表达式语句。
例如上面的代码就可以这样这样写:
int main() { int x, y; cout << "输入两个数进行相除:" << endl; cin >> x >> y; if (y == 0) { throw runtime_error("除数y不能为0."); //runtime_error是一个异常类,也就是表达式 } cout << "x / y = " << x / y << endl; return 0; }
运行结果为:
throw语句只能抛出异常,而解决异常的是try语句块。
三、try语句块
try语句块的通用语法形式是
try { 正常的执行语句 } catch (exception-declaration){ 对异常进行处理的语句 }catch (exception-declaration){ 对异常进行处理的语句 } ...
- 跟在try块之后的是一个或多个catch子句。catch子句包括三部分:关键字 catch、括号内一个(可能未命名的)对象的声明(称作异常声明) 以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。
例如上面的代码又可以改写为:
int main() { int x, y; cout << "输入两个数进行相除:" << endl; while (cin >> x >> y) { try { if (y == 0) { throw runtime_error("除数y不能为0."); } cout << "x / y = " << x / y << endl;![在这里插入图片描述](https://img-blog.csdnimg.cn/149bd2f41f5047d9b6e706d0b7fad6dd.png#pic_center) }//正常想要执行的语句 catch (runtime_error err) {//err为throw语句后面的异常类的对象,也就是异常声明 cout << err.what() << endl; char ch; cout << "是否继续输入(y/Y:继续):"; cin >> ch; if (ch != 'y' && ch != 'Y') { break; } } } return 0; }
err.what() 是runtime_error异常类的一个成员函数,返回值是一个指向c风格字符串,返回值内容为throw runtime_error(“除数y不能为0.”) 括号里面的内容。
运行结果:
当发现异常时,进行catch语句,询问你是否继续。这就是try语句块的用法了。
四、标准异常
C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用 户编写的程序中使用,它们分别定义在4个头文件中:
- exception头文件定义了最通用的异常类exceptiono它只报告异常的发生,不提供任何额外信息。
- dexcep乜头文件定义了几种常用的异常类。
- new头文件定义了 bad_alloc 异常类型
- type_info头文件定义了 bad_cast 异常类型.
< stdexcept > 定义的异常类 | |
---|---|
exception | 最常见的问题 |
runtime_error | 只有在运行时才能检测出的问题 |
range_error | 运行时错误:生成的结果超出了有意义的值域范围 |
overflow_error | 运行时错误:计算上溢 |
underflow_error | 运行时错误:计算下溢 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误:参数对应的结果值不存在 |
invalid_argument | 逻辑错误:无效参数 |
length_error | 逻辑惜误:试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误:使用一个超出有效范围的值 |
-
标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。
-
我们只能以默认初始化的方式初始化exception、 bad alloc和bad cast对象,不允许为这些对象提供初始值。
-
其他异常类型的行为则恰好相反:应该使用string对象或者C风格字符串初始化这些类型的对象,但是不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,该初始值含有错误相关的信息。例如:runtime_error("除数y不能为0.");
-
异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向c风格字符串的const char*。该字符串的目的是提供关于异常的一些文本信息。
-
what函数返回的c风格字符串的内容与异常对象的类型有关,如果异常类型有一个字符串初始值,则what返回该字符串。对于其他无初始值的异常类型来说,what返回的内容由编译器决定。runtime_error(“除数y不能为0.”):该异常类有初始值,所以what()返回 “除数y不能为0.”