// 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;
}