[基础] C++throw详解:异常处理的核心机制(示例代码)


C++ throw 详解:异常处理的核心机制


一、异常处理的基本概念

C++ 中的 throw 是异常处理的核心关键字,用于主动触发异常。异常机制允许程序在检测到错误时,跳出当前执行流程,将控制权交给异常处理器(try-catch 块),从而实现错误的分层管理。


二、throw 的作用与语法

1. 核心作用

  • 错误传递:将错误信息从底层传递到上层调用栈。
  • 流程控制:中断当前函数,寻找匹配的 catch 块。
  • 资源释放:通过栈展开(Stack Unwinding)确保局部对象析构。

2. 语法格式

throw expression; // 抛出一个异常对象(任意类型)

三、基础用法示例

1. 抛出内置类型异常

#include <iostream>
using namespace std;

double divide(int a, int b) {
    if (b == 0) {
        throw "Division by zero!"; // 抛出const char*类型异常
    }
    return static_cast<double>(a) / b;
}

int main() {
    try {
        cout << divide(10, 0) << endl;
    } catch (const char* msg) { // 捕获异常
        cerr << "Error: " << msg << endl;
    }
    return 0;
}

// 输出:Error: Division by zero!

2. 抛出标准库异常

C++ 标准库提供了 <stdexcept> 中预定义的异常类(如 runtime_error),更推荐使用:

#include <stdexcept>

double divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero!");
    }
    return static_cast<double>(a) / b;
}

int main() {
    try {
        divide(10, 0);
    } catch (const std::runtime_error& e) {
        cerr << "Error: " << e.what() << endl;
    }
    return 0;
}

四、自定义异常类

通过继承 std::exception 实现自定义异常,增强可维护性:

#include <exception>
#include <string>

class MyException : public std::exception {
private:
    std::string message;

public:
    MyException(const std::string& msg) : message(msg) {}
    const char* what() const noexcept override {
        return message.c_str();
    }
};

void validate(int value) {
    if (value < 0) {
        throw MyException("Value cannot be negative!");
    }
}

int main() {
    try {
        validate(-5);
    } catch (const MyException& e) {
        cerr << "Custom Error: " << e.what() << endl;
    }
    return 0;
}

// 输出:Custom Error: Value cannot be negative!

五、throw 的高级特性

1. 异常规格(C++17 前)与 noexcept(C++11+)

  • 废弃的异常规格(C++17 前):
    void func() throw(std::runtime_error); // 声明可能抛出std::runtime_error
    
  • 现代替代 noexcept
    void safe_func() noexcept; // 承诺不抛出任何异常
    

2. 重新抛出异常

catch 块中捕获后再次抛出,允许上层处理:

try {
    // 可能抛出异常的代码
} catch (const std::exception& e) {
    cerr << "Log: " << e.what() << endl;
    throw; // 重新抛出当前异常
}

六、异常安全与最佳实践

  1. RAII 原则:使用智能指针、容器等管理资源,确保异常发生时资源自动释放。

    void processFile() {
        std::ifstream file("data.txt");
        if (!file) throw std::runtime_error("File open failed");
        // 文件操作(若异常抛出,file析构会自动关闭句柄)
    }
    
  2. 避免在析构函数中抛出异常:可能导致程序终止(C++默认行为)。

  3. 优先使用标准异常类型:如 invalid_argumentout_of_range 等,保持代码一致性。

  4. 明确异常层次:自定义异常继承自 std::exception,便于统一捕获。


七、综合案例:安全动态数组

结合模板类与异常处理,实现一个类型安全的动态数组:

#include <iostream>
#include <stdexcept>

template <typename T>
class SafeArray {
private:
    T* data;
    size_t size;

public:
    SafeArray(size_t n) : size(n), data(new T[n]) {}
    ~SafeArray() { delete[] data; }

    T& operator[](size_t index) {
        if (index >= size) {
            throw std::out_of_range("Index out of bounds");
        }
        return data[index];
    }

    size_t getSize() const { return size; }
};

int main() {
    try {
        SafeArray<int> arr(5);
        arr[0] = 10;
        arr[5] = 20; // 触发越界异常
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
    return 0;
}

// 输出:Exception caught: Index out of bounds

八、总结

  • 核心作用throw 提供了一种结构化的错误处理机制。
  • 适用场景:函数遇到无法处理的错误时(如无效参数、资源不足)。
  • 关键原则
    • 异常应用于“异常情况”,而非普通控制流。
    • 结合 RAII 保证资源安全。
    • 优先使用标准异常或自定义层次化的异常类。

通过合理使用 throwtry-catch,可以显著提升代码的健壮性和可维护性。


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值