C++速览之异常处理

1、什么是异常?
在计算机程序中,异常是指程序执行过程中发生的错误或异常情况。这些异常可能是由于无效的输入资源不可用逻辑错误等原因引起的。通过使用异常处理机制,程序可以在出现异常时采取相应的措施,如错误处理、资源释放、日志记录等。

2、异常处理的基本原则

异常处理遵循以下基本原则:

2.1抛出异常(Throwing Exceptions):
当出现错误或异常情况时,可以使用 throw 关键字抛出异常。抛出的异常可以是内置类型(如整数、字符等)或自定义类型。

throw MyException("Something went wrong");

2.2 捕获异常(Catching Exceptions):
使用 try-catch 块来捕获和处理异常。try 块用于包裹可能引发异常的代码块,而 catch 块用于捕获并处理特定类型的异常。

try {
    // 可能引发异常的代码块
} catch (ExceptionType ex) {
    // 处理 ExceptionType 类型的异常
}

2.3 处理异常(Handling Exceptions):
catch 块中,可以对捕获的异常进行处理。处理异常的方式可以是输出错误信息、进行日志记录、恢复程序状态等。也可以选择重新抛出异常或抛出其他异常。

try {
    // 可能引发异常的代码块
} catch (ExceptionType1 ex1) {
    // 处理 ExceptionType1 类型的异常
} catch (ExceptionType2 ex2) {
    // 处理 ExceptionType2 类型的异常
} catch (...) {
    // 处理其他类型的异常
}

2.4 栈展开(Stack Unwinding):
当发生异常时,程序会在调用栈中寻找匹配的 catch 块来处理异常。如果没有找到匹配的 catch 块,异常会被传递给上层调用栈中的调用者,直到找到匹配的 catch 块为止。如果最终没有找到任何匹配的 catch 块,程序将终止,并显示未捕获的异常信息。

2.5 异常安全(Exception Safety):
在编写代码时,需要考虑异常安全性。这意味着在出现异常时,程序应保持稳定状态,并确保资源的正确释放,以避免资源泄漏和数据损坏

实例:

#include <iostream>
#include <stdexcept>

double calculateAverage(const double *numbers, int size) {
    if (numbers == nullptr || size <= 0) {
        throw std::invalid_argument("Invalid input");
    }

    double sum = 0;
    for (int i = 0; i < size; i++) {
        sum += numbers[i];
    }

    return sum / size;
}

void processArray(const double *numbers, int size) {
    try {
        double average = calculateAverage(numbers, size);
        std::cout << "Average: " << average << std::endl;
    } catch (std::exception &ex) {
        std::cout << "Exception occurred in calculateAverage(): " << ex.what() << std::endl;
        // 执行错误处理逻辑,如输出错误信息、恢复程序状态等
        throw; // 重新抛出异常
    }
}

void processData(const double *numbers, int size) {
    try {
        processArray(numbers, size);
    } catch (std::exception &ex) {
        std::cout << "Exception occurred in processArray(): " << ex.what() << std::endl;
        // 执行错误处理逻辑,如输出错误信息、恢复程序状态等
        throw; // 重新抛出异常
    }
}

int main() {
    double numbers[] = {1.0, 2.0, 3.0, 4.0, 5.0};

    try {
        processData(numbers, 5);
    } catch (std::exception &ex) {
        std::cout << "Exception occurred in processData(): " << ex.what() << std::endl;
        // 执行错误处理逻辑,如输出错误信息、恢复程序状态等
    }

    return 0;
}

自定义异常类:
在 C++ 中,你可以自定义异常类来表示特定的异常情况。自定义异常类通常继承自标准库中的 std::exception 类,并实现 what() 函数来提供异常的描述信息。

下面是一个自定义异常类的示例:

#include <exception>

class MyException : public std::exception {
public:
    MyException(const char* message) : m_message(message) {}

    const char* what() const noexcept override {
        return m_message;
    }

private:
    const char* m_message;
};

通过自定义异常类,你可以根据程序的需求定义不同类型的异常,并在异常处理器中针对不同类型的异常做出相应的处理。

异常规范(Exception Specifications)
异常规范用于指定函数可能抛出的异常类型。它可以在函数声明中使用 throw 关键字来指定特定的异常类型。然而,C++11 引入了更推荐的异常规范方式,即使用 noexcept 关键字来指示函数不会抛出异常。

void myFunction() noexcept {
    // 不会抛出异常的函数体
}

异常处理的最佳实践

以下是一些在使用异常处理时的最佳实践:

只捕获你知道如何处理的异常:在 catch 块中,只捕获你能够处理的异常类型。不要捕获所有异常类型,以免掩盖潜在的错误。
确保资源的正确释放:在捕获和处理异常时,确保释放已分配的资源,以避免资源泄漏。
避免在构造函数和析构函数中抛出异常:在构造函数和析构函数中抛出异常可能导致不可预料的行为,因此尽量避免在这些函数中抛出异常。
清晰地记录和报告异常:在处理异常时,清晰地记录和报告异常信息,以便进行故障排查和调试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挥剑决浮云 -

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值