c++异常处理exception

// c++中的异常处理
// 1.throw : 专门用于抛出异常,做出提示
// 2.try   : 尝试运行可能会异常的代码
// 3.catch : 用于接收前面跑出来的异常并进行解决

// 执行循序为:
// try
// {
//     throw ...; // 执行的代码中必须直接或者间接的有throw
// }
// catch在throw之后执行,catch执行的数据类型入参与throw抛出异常的数据类型一致
// catch(const std::exception& e)
// {
//     std::cerr << e.what() << '\n';
// }

// try
// {
//     do th1 ... (必须会执行的代码)
//     直接或间接有throw,
//     如果此处没有触发throw则会执行下文的do th2
//     如果此处有触发throw,则下文的do th2不会继续执行,而是之下下文中的chtch
//     因为如果触发throw,则do th2没有继续执行的必要
//     do th2 ... ()
// }
// // const std::exception& e为接收到的异常情况
// catch(const std::exception& e)
// {
//     // 异常处理
//     std::cerr << e.what() << '\n';
// }

// 以上的try catch可以层层嵌套使用
// 在 C++ 中,可以通过嵌套 `try-catch` 来处理更复杂的异常情况,即在一个 `try` 块中嵌套另一个 `try` 块。
// 在嵌套结构中,内部的 `try` 块可以处理外部 `try` 块无法处理的异常。
// 下面是一个嵌套 `try-catch` 的示例代码:
// try {
//     try {
//         // Block of code which may throw an exception
//     } catch (const SomeExceptionType& e) {
//         // Exception handling code for inner try block
//     }
//     // Block of code which may throw another exception
// } catch (const AnotherExceptionType& e) {
//     // Exception handling code for outer try block
// }
// 在上面的代码中,有两个 `try` 块,其中内部的 `try` 块包含一个代码块,可能会引发某种类型的异常。
// 如果在内部的 `try` 块中抛出异常,它将被内部的 `catch` 块捕获和处理。 
// 如果在内部的 `try` 块中未发生异常,则执行内部 `try` 块后的代码块。
// 如果在这个代码块中引发了异常,那么这个异常将被外部的 `catch` 块捕获和处理。
// 需要注意的是,如果一个 `catch` 块捕获了异常,它将防止此异常进一步传播到该代码块之外。
// 因此,如果一个 `catch` 块在处理异常时,抛出了另一个异常,则外部的 `catch` 块将无法捕获最初被抛出的异常,
// 也就是说,只有最内层的 `catch` 块可以捕获到抛出的异常。

// 注意:
// 只要有throw抛出了异常,后边就必须有catch就就收异常进行异常处理,这是语法规定。

#include <iostream>
#include <string>

using namespace std;

int test(int a, int b)
{
    // 当b==0时,正常的处理已经不能继续,必须进行异常处理
    if (b == 0.0)
    {
        // 有异常情况->需要通过throw进行报告
        // 通过throw + 抛出的异常信息;
        // 抛出的异常信息:支持多种类型
        throw "这里有问题!";
        // 第一个throw抛出异常后,后边的throw不会再继续执行,因为已经没有意义
        // 注意:throw不是return,如果这里有throw,则在后边的代码实现中必须要有catch进行异常处理
        throw 666;
        // 如果char数据类型报错信息后没有对应数据类型的catch处理函数,那么将会出现如下报错
        // terminate called after throwing an instance of 'char'
        // Aborted (core dumped)
        throw 'S';
        // 如果double数据类型报错信息后没有对应数据类型的catch处理函数,那么将会出现如下报错
        // terminate called after throwing an instance of 'char'
        // Aborted (core dumped)
        throw 3.14;
    }
    return a / b;
}

int main()
{
    // 异常情况,num没有初始化
    int num;
    int val = num;
    try
    {
        cout << test(9, 0) << endl;
    }
    // const std::exception& e参数类型为throw抛出异常时对应的参数类型
    // 参数 `const std::exception& e` 表示捕获任何派生自 `std::exception` 类的异常对象
    // `std::exception` 是 C++ STL 标准库中所有异常类型的基类,它定义了一些常用的成员函数和属性,
    // 例如 `what()` 函数,可以用于获取异常对象的描述信息。
    // 派生自 `std::exception` 的标准异常类包括 `std::runtime_error`、`std::logic_error` 和 `std::bad_alloc` 等。
    // 使用 `catch(const std::exception& e)` 的语法,表示捕获所有继承自 `std::exception` 的异常类型,
    // 以确保我们能够捕获可能发生的异常,并提供恰当的异常处理机制。
    // 需要注意的是,不是所有异常都派生自 `std::exception`,例如内存访问错误、空指针异常等异常就不属于该类型。
    // 此时,我们需要使用其他适当的异常类来捕获这些异常。
    // 另外,如果你想自定义异常,可以使用继承自 `std::exception` 的新类,并为它提供自己的行为和描述信息。
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
    // 此处catch处理的异常信息为throw抛出异常时的char *类型异常信息
    catch (const char * str) {
        cout << str << endl;
    }
    // 此处catch处理的异常信息为throw抛出异常时的int类型异常信息
    catch (int num) {
        cout << num << endl;
    }
    // "..."适配所有数据类型的异常信息
    // 比如上文中的throw 3.14;并没有对应的catch函数,
    // 那么如果throw 3.14;抛出将会在此处的catch (...)处理
    catch (...) {
        cout << "有问题" << endl;
    }

    return 0;
}

c++自定义异常来自于c++标准提供的类:

// c++自定义异常处理类
// 自定义异常处理语法格式:try { throw } catch (const MyExpection& obj) {}
#include <iostream>
#include <exception>

using namespace std;

// std::exception为c++标准异常处理的共同父类,可以使用该类派生出子类实现自定义异常处理
class MyExpection : public std::exception
{
public:
    // const char *what const {}
    // 以上定义方法会报错:
    // error: looser throw specifier for ‘virtual const char* MyExpection::what() const’
    // error:   overriding ‘virtual const char* std::exception::what() const noexcept’
    // what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
    // 这个错误是因为虚函数 `what()` 的异常规范(或 throw specifier)与被覆盖的基类中的不同导致的。
    // 异常规范告诉编译器,在函数抛出的异常类型方面可以期望什么。
    // 在这里,`const char* MyExpection::what() const` 声明的异常规范应该与 `std::exception::what()` 的规范保持一致。
    // 在 C++11 中,标准库异常类的 `what()` 声明是 `virtual const char* what() const noexcept`。
    // `noexcept` 告诉编译器,该函数不会抛出任何异常。
    // 因此,在自定义异常中,需要将 `what()` 函数的异常规范改为 `noexcept`,以与基类中的异常规范保持一致。
    // 此外,也可以忽略异常规范,这意味着函数可以抛出任何异常,包括派生自 `std::exception` 的异常类型。
    // 不过,需要注意的是,忽略异常规范可能会影响代码的可移植性,因为某些编译器可能依赖于异常规范进行一些优化。
    // 如果你决定忽略异常规范,请确保在实际编译器中测试你的代码。
    // 修复后的代码如下:
    const char *what() const noexcept override {
        return "exception !!!";
    }
};

int main()
{
    // 可以转到exception类中定义查看具体实现和使用接口
    MyExpection obj;
    cout << obj.what() << endl;

    try {
        throw MyExpection();
    } catch(const MyExpection& obj) {
        std::cerr << obj.what() << '\n';
    }

    return 0;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值