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++允许抛出任何类型的异常,包括:

  1. 基本数据类型:如intchar

代码语言:javascript

代码运行次数:0

运行

AI代码解释

throw 404; // 抛出整数异常
throw "Not found"; // 抛出字符串字面量异常
  1. 自定义类型:通常是类或结构体

代码语言:javascript

代码运行次数:0

运行

AI代码解释

class MyException {
private:
    string message;
public:
    MyException(string msg) : message(msg) {}
    string getMessage() const { return message; }
};

// 抛出自定义异常
throw MyException("发生了错误");
  1. 标准库异常: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) {
    // ...
}
异常处理的最佳实践
  1. 只在异常情况下使用异常:不要将异常用于常规控制流
  2. 捕获适当的异常类型:避免过度使用​​catch(...)​
  3. 按引用捕获异常:避免异常对象的复制,同时允许捕获派生类异常

代码语言:javascript

代码运行次数:0

运行

AI代码解释

catch (const MyException& e) { // 推荐使用const引用
    // ...
}
  1. 清理资源:使用RAII(资源获取即初始化)技术确保资源正确释放
  2. 异常安全:设计函数时考虑异常发生时的状态一致性
异常的优缺点

优点

  • 分离正常代码和错误处理代码,提高可读性
  • 可以在调用链的任意层次处理异常,不必每层都检查错误
  • 能够传递更丰富的错误信息

缺点

  • 可能影响性能(异常处理代码通常不被编译器优化)
  • 过度使用会使程序逻辑变得复杂
  • 可能导致资源泄露(如果没有正确处理)
示例:完整的异常处理程序

代码语言: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​​块捕获并处理这个异常,确保程序能够优雅地处理错误情况。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐