一、异常的概念及使用
1. 异常的概念
异常处理机制允许程序中独立开发的部分在运行时出现问题时进行通信并做出相应处理。它使得问题的检测与解决过程分离:一部分负责检测问题,另一部分负责处理,检测环节无需知晓处理模块的所有细节。
C 语言主要通过错误码处理错误,本质是对错误信息分类编号,拿到错误码后还需查询具体信息,比较繁琐。而 C++ 异常抛出的是一个对象,可以包含更全面的各类信息。
2. 异常的抛出和捕获
程序出现问题时,我们通过 throw 一个对象来引发异常。该对象的类型及当前调用链决定了应由哪个 catch 代码来处理。被选中的处理代码是调用链中与该对象类型匹配且离抛出位置最近的那一个。
当 throw 执行时,后续语句不再执行。程序从 throw 位置跳转到匹配的 catch 模块,控制权发生转移。这里有两个重要含义:
- 沿着调用链的函数可能提早退出。
- 一旦开始执行异常处理程序,沿调用链创建的对象都将销毁。
抛出异常对象后,会生成一个拷贝(类似于函数传值返回),因为抛出的可能是局部对象。这个拷贝对象会在 catch 子句结束后销毁。
3. 栈展开
抛出异常后,程序暂停当前函数执行,寻找匹配的 catch 子句。首先检查 throw 是否在 try 块内部,若有则查找匹配;若当前函数无 try/catch 或类型不匹配,则退出当前函数,在外层调用链中继续查找。这个过程被称为栈展开。
如果到达 main 函数仍未找到匹配,程序会调用标准库的 terminate 函数终止。若找到匹配的处理代码,catch 子句代码会继续执行。
double Divide(int a, int b) {
try {
// 当 b == 0 时抛出异常
if (b == 0) {
std::string s("Divide by zero condition!");
throw s;
} else {
return ((double)a / (double)b);
}
} catch (int errid) {
std::cout << errid << std::endl;
}
return 0;
}
void Func() {
int len, time;
std::cin >> len >> time;
{
std::cout << (len, time) << std::endl;
} ( * errmsg) {
std::cout << errmsg << std::endl;
}
std::cout << __func__ << << __LINE__ << << std::endl;
}
{
() {
{
();
} ( std::string& errmsg) {
std::cout << errmsg << std::endl;
}
}
;
}


