一、异常的概念及使用
1. 异常的概念
- 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理。异常使得我们能够将问题的检测与解决问题的过程分开:程序的一部分负责检测问题的出现,然后将解决问题的任务传递给程序的另一部分。检测环节无须知道问题的处理模块的所有细节。
- C 语言主要通过错误码的形式处理错误。错误码本质是对错误信息进行分类编号,拿到错误码后还需查询具体含义,较为繁琐。而异常通过抛出一个对象来传递错误,该对象可以包含更全面的信息。
2. 异常的抛出和捕获
- 程序出现问题时,通过
throw抛出一个对象来引发异常。该对象的类型以及当前的调用链决定了应由哪个catch处理代码来处理该异常。 - 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。根据抛出对象的类型和内容,抛出部分告知处理部分具体发生了什么错误。
- 当
throw执行时,throw后面的语句将不再执行。程序的执行流从throw位置跳转到与之匹配的catch模块。catch可能是同一函数中的局部catch,也可能是调用链中另一个函数中的catch。这里有两个重要含义:- 沿着调用链的函数可能提早退出。
- 一旦程序开始执行异常处理程序,沿着调用链创建的对象都将按逆序销毁。
- 抛出异常对象后,会生成该异常对象的拷贝。因为抛出的异常对象可能是一个局部对象,所以会生成一个拷贝对象,该拷贝对象会在
catch子句执行完毕后销毁(处理机制类似于函数的传值返回)。
3. 栈展开
- 抛出异常后,程序暂停当前函数的执行,开始寻找与之匹配的
catch子句。首先检查throw本身是否在try块内部,如果是则查找匹配的catch语句。若有匹配,则跳转到catch处进行处理。 - 如果当前函数中没有
try/catch子句,或者类型不匹配,则退出当前函数,继续在外层调用函数链中查找。上述查找catch的过程被称为栈展开。 - 如果到达
main函数依旧没有找到匹配的catch子句,程序会调用标准库的std::terminate函数终止程序。
如果找到匹配的 catch 子句并处理完毕,catch 子句后的代码将继续执行。

double Divide(int a, int b) {
try {
// 当 b == 0 时抛出异常
if (b == 0) {
string s;
s;
} {
(()a / ()b);
}
} ( errid) {
cout << errid << endl;
}
;
}
{
len, time;
cin >> len >> time;
{
cout << (len, time) << endl;
} ( * errmsg) {
cout << errmsg << endl;
}
cout << __FUNCTION__ << << __LINE__ << << endl;
}
{
() {
{
();
} ( string& errmsg) {
cout << errmsg << endl;
}
}
;
}



