基本概念
异常处理用于处理程序运行时发生的错误,将“错误检测”与“错误处理”分离。
- 抛出异常:使用
throw表达式 - 捕获异常:使用
try–catch块 - 传播:若当前函数未捕获,异常沿调用栈向上传递;直到
main仍未捕获则调用terminate()终止程序
基本语法
#include <iostream>
using namespace std;
double divide(double a, double b) {
if (b == 0)
throw "除数不能为零"; // 抛出 const char* 类型的异常
return a / b;
}
int main() {
try {
double result = divide(10, 0);
cout << result << endl;
}
catch (const char* msg) { // 捕获 const char* 异常
cerr << "错误: " << msg << endl;
}
return 0;
}
输出:错误: 除数不能为零
throw 表达式
throw 可以抛出任何类型的对象(基本类型、指针、类对象)。通常抛出派生自 std::exception 的类对象。
throw 42; // 抛出 int
throw "error"; // 抛出 const char*
throw MyException(); // 抛出自定义类对象
throw; // 重新抛出当前捕获的异常(仅在 catch 块内使用)
重新抛出示例:
try {
// ...
}
catch (...) { // 捕获所有异常
// 做一些清理工作
throw; // 将原异常继续向上传递
}
try–catch 块
多个 catch 子句
按顺序匹配,一旦匹配成功,后续 catch 不再执行。应把更特化的类型放在前面。
try {
// code
}
catch (int e) {
cout << "捕获整数异常: " << e << endl;
}
catch (const char* e) {
cout << "捕获字符串异常: " << e << endl;
}
catch (...) { // 捕获任何未被上面匹配的异常
cout << "未知异常" << endl;
}
按引用捕获
推荐按 const 引用 捕获,避免对象拷贝及 slicing(派生类被切为基类)。
catch (const exception& e) {
cerr << e.what() << endl;
}
函数内的 try/catch
整个函数体可以用 try 包裹:
void func() try {
// 函数体
}
catch (const exception& e) {
// 处理
}
这种形式常用于构造函数初始化列表中抛出异常的情况。
标准异常类(了解,不重要)
C++ 标准库提供 <stdexcept> 中的异常类层次,所有异常都继承自基类 exception(位于 <exception>)。
常用标准异常
| 异常类 | 头文件 | 说明 |
|---|---|---|
exception | <exception> | 所有标准异常的基类 |
logic_error | <stdexcept> | 逻辑错误,程序可预判 |
domain_error | <stdexcept> | 定义域错误 |
invalid_argument | <stdexcept> | 无效参数 |
length_error | <stdexcept> | 长度过长 |
out_of_range | <stdexcept> | 超出范围(如 vector::at()) |
runtime_error | <stdexcept> | 运行时错误,难以预判 |
range_error | <stdexcept> | 内部计算范围错误 |
overflow_error | <stdexcept> | 算术上溢 |
underflow_error | <stdexcept> | 算术下溢 |
bad_alloc | <new> | new 分配失败 |
bad_cast | <typeinfo> | dynamic_cast 失败(引用) |
使用示例
#include <stdexcept>
#include <iostream>
using namespace std;
int getCharAt(const string& s, int idx) {
if (idx < 0 || idx >= s.size())
throw out_of_range("索引超出范围");
return s[idx];
}
int main() {
try {
getCharAt("hello", 10);
}
catch (const out_of_range& e) {
cerr << "out_of_range: " << e.what() << endl;
}
catch (const exception& e) { // 捕获其他标准异常
cerr << "exception: " << e.what() << endl;
}
return 0;
}
what() 成员函数返回错误描述字符串。
自定义异常类(略,不重要)
继承自 std::exception(或它的派生类),并覆盖 what()。
#include <exception>
#include <iostream>
#include <cstring>
using namespace std;
class MyException : public exception {
private:
char msg[100];
public:
MyException(const char* errorMsg) {
strncpy(msg, errorMsg, sizeof(msg) - 1);
msg[sizeof(msg)-1] = '\0';
}
const char* what() const noexcept override {
return msg;
}
};
// 更简洁的方式:继承 runtime_error
#include <stdexcept>
class MyRuntimeError : public runtime_error {
public:
MyRuntimeError(const string& msg) : runtime_error(msg) {}
};
int main() {
try {
throw MyException("自定义错误");
}
catch (const MyException& e) {
cerr << e.what() << endl;
}
return 0;
}
注意:what() 应声明为 noexcept,且不应抛出异常。
noexcept 说明符
声明函数不会抛出异常。
可用 noexcept(expression) 根据条件决定是否 noexcept。