一、异常的概念及使用
1、异常的概念
- 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理,异常使得我们能够将问题的检测与解决问题的过程分开,程序的一部分负责检测问题的出现,然后解决问题的任务传递给程序的另一部分,检测环节无须知道问题的处理模块的所有细节。
- C 语言主要通过错误码的形式处理错误,错误码本质就是对错误信息进行分类编号,拿到错误码以后还要去查询错误信息,比较麻烦。异常时抛出一个对象,这个对象可以含更全面的各种信息。
2、异常的抛出和捕获
- 程序出现问题时,我们通过抛出 (throw) 一个对象来引发一个异常,该对象的类型以及当前的调用链决定了应该由哪个 catch 的处理代码来处理该异常。
- 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。根据抛出对象的类型和内容,程序的抛出异常部分告知异常处理部分到底发生了什么错误。
- 当 throw 执行时,throw 后面的语句将不再被执行。程序的执行从 throw 位置跳到与之匹配的 catch 模块,catch 可能是同一函数中的一个局部的 catch,也可能是调用链中另一个函数中的 catch,控制权从 throw 位置转移到了 catch 位置。这里还有两个重要的含义:
- 沿着调用链的函数可能提早退出。
- 一旦程序开始执行异常处理程序,沿着调用链创建的对象都将销毁。
- 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个局部对象,所以会生成一个拷贝对象,这个拷贝的对象会在 catch 子句后销毁。(这里的处理类似于函数的传值返回)
3、栈展开
- 抛出异常后,程序暂停当前函数的执行,开始寻找与之匹配的 catch 子句,首先检查 throw 本身是否在 try 块内部,如果在则查找匹配的 catch 语句,如果有匹配的,则跳到 catch 的地方进行处理。
- 如果当前函数中没有 try/catch 子句,或者有 try/catch 子句但是类型不匹配,则退出当前函数,继续在外层调用函数链中查找,上述查找的 catch 过程被称为栈展开。
- 如果到达 main 函数,依旧没有找到匹配的 catch 子句,程序会调用标准库的 terminate 函数终止程序。
如果找到匹配的 catch 子句处理后,catch 子句代码会继续执行。
#include <iostream>
using namespace std;
doubleDivide(int a, int b) {
try {
// 当 b == 0 时抛出异常
if (b == 0) {
string s("Divide by zero condition!");
throw s;
} else {
return ((double)a / (double)b);
}
} catch (int errid) {
cout << errid << endl;
}
return 0;
}
{
len, time;
cin >> len >> time;
{
cout << (len, time) << endl;
} ( * errmsg) {
cout << errmsg << endl;
}
cout << __FUNCTION__ << << __LINE__ << << endl;
}
{
() {
{
();
} ( string& errmsg) {
cout << errmsg << endl;
}
}
;
}


