C++ 异常处理
·
C++ 异常处理
一、概述
1.1 程序中的两类错误
| 错误类型 | 说明 | 捕获时机 |
|---|---|---|
| 语法错误 | 代码不符合语言规范 | 编译时(编译系统发现) |
| 运行错误 | 程序逻辑引发的意外(如下标越界、内存分配失败) | 运行时 |
1.2 为什么需要异常处理
在设计程序时,应当事先分析程序运行时可能出现的各种意外情况,制订出相应的处理措施,这就是程序的异常处理任务。
- 没有异常处理:运行出现异常时,程序只能终止运行
- 有异常处理:程序按照预设的处理流程,转到异常处理代码段执行,而不会崩溃
1.3 C 语言 vs C++ 的异常处理方式
| 语言 | 处理方式 |
|---|---|
| C | 通常由被调用函数返回一个数值作为错误标记 |
| C++ | 函数可识别异常条件,通过 throw 抛出异常,由 catch 捕获处理 |
二、三个关键字:try / catch / throw
异常提供了一种转移程序控制权的方式。C++ 异常处理涉及三个关键字:
throw → 抛出异常(当问题出现时)
↓
try → 保护代码块(放置可能抛出异常的代码)
↓
catch → 捕获并处理异常
| 关键字 | 作用 |
|---|---|
throw |
当问题出现时,程序抛出一个异常 |
catch |
在想要处理问题的地方,通过异常处理程序捕获异常 |
try |
标识将被激活的特定异常的代码块,后面通常跟着一个或多个 catch 块 |
try块中放置可能抛出异常的代码,称为保护代码。
三、示例代码
从键盘输入两个数,实现相除:
#include <iostream>
using namespace std;
/*
* 从键盘输入两个数,实现相除
*/
int main()
{
double x, y;
cout << "请输入xy的值";
cin >> x >> y;
try {
if (y == 0)
throw -1; // 抛出 int 类型异常
else if (x == 0)
throw -1.0; // 抛出 double 类型异常
else
cout << "x/y=" << x / y << endl << endl;
}
catch (int e) {
cout << "catch(int):" << e << endl;
}
catch (double d) {
cout << "catch(double):" << d << endl;
}
return 0;
}

代码解析
try {
if (y == 0)
throw -1; // ① 除数为 0 → 抛出 int 异常 → 跳到 catch(int)
else if (x == 0)
throw -1.0; // ② 被除数为 0 → 抛出 double 异常 → 跳到 catch(double)
else
cout << "x/y=" << x / y << endl; // ③ 正常执行
}
catch (int e) { /* 捕获 int 异常 */ }
catch (double d) { /* 捕获 double 异常 */ }
| 输入 | 抛出的异常类型 | 匹配的 catch |
|---|---|---|
| y = 0 | throw -1(int) |
catch(int e) |
| x = 0 | throw -1.0(double) |
catch(double d) |
| x, y 均非 0 | 不抛出异常,正常计算 | 不走 catch |
四、执行流程
程序正常执行
↓
进入 try 块
↓
是否抛出异常?
/ \
否 是
↓ ↓
正常执行 匹配 catch 块
↓ ↓
跳过 catch 执行异常处理代码
↓
程序继续
一旦抛出异常,
try块中抛出点之后的代码不会被执行,控制权立即转移到匹配的catch块。
五、补充知识点
5.1 标准异常类
C++ 标准库提供了异常类层次结构,位于 <stdexcept> 头文件中:
#include <stdexcept>
try {
throw std::runtime_error("运行时出错");
}
catch (const std::exception& e) {
cout << e.what() << endl; // 输出异常信息
}
5.2 catch 的匹配规则
catch按照书写顺序从上到下匹配- 派生类异常应写在基类异常前面(否则会被基类 catch 截获)
catch(...)可以捕获所有类型的异常(通常放在最后)
try {
// ...
}
catch (const std::runtime_error& e) { /* 先匹配派生类 */ }
catch (const std::exception& e) { /* 再匹配基类 */ }
catch (...) { /* 兜底捕获所有 */ }
5.3 异常重新抛出
在 catch 块中可以用 throw;(不加参数)将异常继续向外抛出:
catch (int e) {
cout << "记录日志:" << e << endl;
throw; // 重新抛出,交给上层处理
}
更多推荐
所有评论(0)