错误处理 <exception>

C++ 提供了一个全面的错误处理机制,主要通过异常处理机制来实现。异常处理允许程序在遇到错误条件时,将控制权转移到处理错误的代码部分,而不是简单地终止程序。<exception> 头文件定义了异常处理机制的核心类和函数。以下是 <exception> 头文件中的主要内容及其用法:

1. 异常类

C++ 的异常处理机制基于类的继承体系。<exception> 头文件定义了几个重要的异常类,它们可以作为用户定义异常的基类。

std::exception

std::exception 是所有标准异常类的基类。它提供了一个虚拟的 what() 方法,用于获取异常的描述信息。

#include <iostream>
#include <exception>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "MyException occurred";
    }
};

int main() {
    try {
        throw MyException();
    } catch (const std::exception& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }
    return 0;
}

std::runtime_error

std::runtime_error 继承自 std::exception,用于表示运行时错误。它的构造函数接受一个描述错误的字符串。

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("Runtime error occurred");
    } catch (const std::runtime_error& e) {
        std::cout << "Runtime error: " << e.what() << std::endl;
    }
    return 0;
}

std::logic_error

std::logic_error 继承自 std::exception,用于表示逻辑错误,例如函数参数不合法等情况。

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::logic_error("Logic error occurred");
    } catch (const std::logic_error& e) {
        std::cout << "Logic error: " << e.what() << std::endl;
    }
    return 0;
}

2. 异常处理机制

C++ 的异常处理机制由 trycatchthrow 关键字组成。

throw

throw 关键字用于抛出异常。异常对象可以是任何类型,但通常是从 std::exception 继承的类。

void mayThrow(bool shouldThrow) {
    if (shouldThrow) {
        throw std::runtime_error("An error occurred");
    }
}

trycatch

try 块用于包含可能会抛出异常的代码,catch 块用于处理这些异常。catch 块可以捕捉不同类型的异常。

try {
    mayThrow(true);
} catch (const std::runtime_error& e) {
    std::cout << "Caught runtime error: " << e.what() << std::endl;
} catch (const std::exception& e) {
    std::cout << "Caught exception: " << e.what() << std::endl;
}

3. 异常的传播

当异常被抛出时,它会沿调用栈向上传播,直到找到合适的 catch 块。如果没有找到合适的 catch 块,程序会终止。

void funcB() {
    throw std::runtime_error("Error in funcB");
}

void funcA() {
    funcB();
}

int main() {
    try {
        funcA();
    } catch (const std::runtime_error& e) {
        std::cout << "Caught: " << e.what() << std::endl;
    }
    return 0;
}

4. 异常安全

编写异常安全的代码可以确保在异常发生时,程序能够正常恢复。异常安全的代码通常使用 RAII(Resource Acquisition Is Initialization)技术来管理资源。

RAII

RAII 是一种编程技术,它确保资源(如内存、文件句柄)在对象的生命周期内自动分配和释放。智能指针和其他资源管理类通常采用 RAII 技术来提供异常安全保障。

#include <iostream>
#include <memory>

void mayThrow(bool shouldThrow) {
    if (shouldThrow) {
        throw std::runtime_error("Error occurred");
    }
}

int main() {
    try {
        std::unique_ptr<int> ptr = std::make_unique<int>(10);
        mayThrow(true);  // 会抛出异常
    } catch (const std::runtime_error& e) {
        std::cout << "Caught: " << e.what() << std::endl;
    }
    // std::unique_ptr 会自动释放内存
    return 0;
}

5. 自定义异常

用户可以创建自己的异常类,继承自标准异常类(如 std::exception)或其他异常类。这样可以提供更具体的错误信息。

#include <iostream>
#include <exception>

class CustomException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Custom exception occurred";
    }
};

int main() {
    try {
        throw CustomException();
    } catch (const CustomException& e) {
        std::cout << "Caught custom exception: " << e.what() << std::endl;
    }
    return 0;
}

6. 总结

<exception> 头文件提供了 C++ 异常处理机制的核心功能,包括标准异常类(如 std::exceptionstd::runtime_errorstd::logic_error)和异常处理语法(trycatchthrow)。使用异常处理可以提高程序的鲁棒性和可维护性,但编写异常安全的代码同样重要。通过 RAII 和自定义异常类,程序员可以更好地管理资源和处理特定错误情况。