C++异常详细介绍
C++异常是一种处理程序运行时错误的机制,它允许程序在检测到错误时跳转到预定义的错误处理代码,而不必通过函数返回值层层传递错误信息。
异常的基本概念
- 异常抛出(throw):当程序检测到错误时,使用
throw关键字抛出一个异常对象 - 异常捕获(catch):使用
try-catch块捕获并处理抛出的异常 - 异常传播:如果当前函数不能处理异常,异常会沿着函数调用栈向上传播,直到找到合适的处理代码
异常处理的基本语法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
try {// 可能抛出异常的代码if (error_condition) {throw exception_object; // 抛出异常}
}
catch (exception_type1 e) {// 处理type1类型的异常
}
catch (exception_type2 e) {// 处理type2类型的异常
}
catch (...) {// 处理所有其他类型的异常(通配符)
}
异常类型
C++允许抛出任何类型的异常,包括:
- 基本数据类型:如
int、char等
代码语言:javascript
代码运行次数:0
运行
AI代码解释
throw 404; // 抛出整数异常
throw "Not found"; // 抛出字符串字面量异常
- 自定义类型:通常是类或结构体
代码语言:javascript
代码运行次数:0
运行
AI代码解释
class MyException {
private:string message;
public:MyException(string msg) : message(msg) {}string getMessage() const { return message; }
};// 抛出自定义异常
throw MyException("发生了错误");
- 标准库异常:C++标准库提供了一系列异常类,定义在
<exception>头文件中,主要包括:
-
std::exception:所有标准异常的基类 -
std::runtime_error:运行时错误 -
std::logic_error:逻辑错误 -
std::out_of_range:超出范围错误(如数组越界) -
std::invalid_argument:无效参数错误
异常规范(C++11前)
早期C++允许使用异常规范指定函数可能抛出的异常类型:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// 声明该函数可能抛出int或string类型的异常
void func() throw(int, string) {// ...
}// 声明该函数不抛出任何异常
void func() throw() {// ...
}
C++11引入了noexcept关键字替代异常规范:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
// 声明该函数不会抛出任何异常
void func() noexcept {// ...
}// 条件性noexcept
void func() noexcept(condition) {// ...
}
异常处理的最佳实践
- 只在异常情况下使用异常:不要将异常用于常规控制流
- 捕获适当的异常类型:避免过度使用
catch(...) - 按引用捕获异常:避免异常对象的复制,同时允许捕获派生类异常
代码语言:javascript
代码运行次数:0
运行
AI代码解释
catch (const MyException& e) { // 推荐使用const引用// ...
}
- 清理资源:使用RAII(资源获取即初始化)技术确保资源正确释放
- 异常安全:设计函数时考虑异常发生时的状态一致性
异常的优缺点
优点:
- 分离正常代码和错误处理代码,提高可读性
- 可以在调用链的任意层次处理异常,不必每层都检查错误
- 能够传递更丰富的错误信息
缺点:
- 可能影响性能(异常处理代码通常不被编译器优化)
- 过度使用会使程序逻辑变得复杂
- 可能导致资源泄露(如果没有正确处理)
示例:完整的异常处理程序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
#include <iostream>
#include <stdexcept>
#include <string>using namespace std;// 除法函数,当除数为0时抛出异常
double divide(double num, double den) {if (den == 0) {throw invalid_argument("除数不能为0");}return num / den;
}int main() {try {double result = divide(10, 0);cout << "结果: " << result << endl;}catch (const invalid_argument& e) {cerr << "错误: " << e.what() << endl;}catch (...) {cerr << "发生了未知错误" << endl;}return 0;
}
这个例子中,divide函数在检测到除数为0时抛出invalid_argument异常,main函数中的try-catch块捕获并处理这个异常,确保程序能够优雅地处理错误情况。
