c++中的try-catch及throw

C++ 使用 try-catch 语句来捕获和处理异常。try 块包含可能发生错误的代码,而 catch 块则用来捕获并处理错误。

try-catch 语句的基本结构

try {
    // 可能抛出异常的代码
} catch (exception_type1 e1) {
    // 处理异常类型 1
} catch (exception_type2 e2) {
    // 处理异常类型 2
} catch (...) {
    // 捕获所有类型的异常
}

具体解释:

  1. try 块

    try 块包含可能发生异常的代码。

    如果 try 块中的代码发生了异常,程序会跳转到相应的 catch 块进行异常处理。

  2. catch 块

    catch 用来捕获由 try 块抛出的异常,并进行处理。

    可以有多个 catch 块,每个 catch 块负责处理特定类型的异常。

    如果 catch 中的异常类型与抛出的异常类型匹配,程序会执行该 catch 块中的代码。

  3. catch (...)

    catch(...) 是一个通配符,用来捕获所有类型的异常。

    这在无法确定抛出异常的具体类型时特别有用

举两个例子说明

  1. 第一个例子

    #include <iostream>
    using namespace std;
    
    int main() {
        try {
            int a = 5;
            int b = 0;
            if (b == 0) {
                throw "Division by zero error!";
            }
            cout << a / b << endl;
        } catch (const char* e) {
            cout << "Error: " << e << endl;  // 捕获并处理除零错误
        }
        return 0;
    }
    

    输出如下:

    img

    解释:

    在 try 块中,程序尝试执行可能出错的代码。

    如果发生异常(这里是通过 throw 手动抛出除零错误),catch 块会捕获到异常并进行处理。

  • 第二个例子

    #include <iostream>
    #include <stdexcept>  // 包含异常类
    
    using namespace std;
    
    int main() {
        try {
            int a = 10, b = 0;
            if (b == 0) {
                throw std::runtime_error("Division by zero error!"); // 抛出运行时错误
            }
            cout << a / b << endl;
        } catch (const std::runtime_error& e) {
            cout << "Caught a runtime error: " << e.what() << endl;  // 捕获并处理 std::runtime_error
        } catch (const std::exception& e) {
            cout << "Caught a general exception: " << e.what() << endl;  // 捕获所有 std::exception 类型的异常
        } catch (...) {
            cout << "Caught an unknown error!" << endl;  // 捕获其他所有类型的异常
        }
        
        return 0;
    }
    

    输出如下:

    img

    解释:

    try 块中的代码试图执行可能会抛出异常的操作。例如,在这个例子中,我们故意将 b 设置为 0,模拟除零错误。

    如果程序遇到除零错误,抛出一个 std::runtime_error 类型的异常。

    catch (const std::runtime_error& e) 块捕获 std::runtime_error 类型的异常,并输出错误信息。

    catch (const std::exception& e) 是更广泛的异常类型,它会捕获所有继承自 std::exception 类的异常(包括 std::runtime_error)。

    catch (...) 捕获所有其他类型的异常,确保即使没有明确处理某种异常类型,程序也不会崩溃。

throw 语句:抛出异常

在 C++ 中,throw 关键字用于抛出异常。可以在任何地方抛出异常,通常是在遇到错误或不符合预期的条件时。

throw some_exception;  // 抛出一个异常

常见的异常类型

C++ 标准库定义了几种常见的异常类型。可以选择抛出这些异常类型之一,或者创建自己的异常类。

  • std::exception:这是所有标准异常类的基类,所有其他标准异常类都继承自它。

  • std::runtime_error:运行时错误,表示程序运行时发生的错误。

  • std::logic_error:逻辑错误,表示程序的逻辑上有问题,比如越界访问数组等。

  • std::out_of_range:越界错误,通常用于容器类(如 std::vector)访问越界元素时抛出的异常。

  • std::invalid_argument:无效参数错误,表示传递给函数的参数不合法。

  • std::bad_alloc:内存分配错误,当 new 操作失败时抛出此异常。

自定义异常类

也可以创建自己的异常类,继承自 std::exception 或其派生类,以便在程序中抛出和捕获特定类型的异常。

#include <iostream>
#include <exception>

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

int main() {
    try {
        throw MyException();  // 抛出自定义异常
    } catch (const MyException& e) {
        std::cout << "Caught custom exception: " << e.what() << std::endl;
    }

    return 0;
}

输出如下:

img

异常的传播和处理

当 throw 抛出异常时,异常会沿着调用栈向上传递,直到找到一个匹配的 catch 块。

如果没有合适的 catch 块捕获异常,程序会终止并显示未处理的异常信息。

比如:

#include <iostream>
#include <stdexcept>  // 包含标准异常类型

using namespace std;

int main() {
    try {
        cout << "Throwing an exception..." << endl;
        throw std::runtime_error("This is a runtime error!");  // 抛出一个运行时错误
    }
    // 这里只捕获 std::logic_error 类型的异常,忽略 std::runtime_error
    catch (const std::logic_error& e) {
        cout << "Caught logic_error: " << e.what() << endl;
    }

    cout << "This will not be printed if an exception is thrown!" << endl;
    return 0;
}

输出如下:

img

异常处理的注意事项

异常的安全性:捕获异常时要确保程序的状态一致性。如果在 catch 块中处理异常时发生了额外的错误,可能导致程序不稳定。

性能问题:异常处理会增加程序的运行时开销,尤其是在频繁抛出和捕获异常的情况下。因此,异常处理应该只用于真正的错误,而不是正常的程序流控制。

posted @   hisun9  阅读(982)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示