2024.3.18记

昨日总结

周末休息,晚上只看了约半个小时的《曾国藩传》,未完成周六的一道leetcode题目。

今日计划

继续学习多线程编程
完成一道leetcode题目。

学习内容

c++ 异常

异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。C++异常处理包括:

  1. throw表达式,异常检测部分使用throw表达式来表示她遇到了无法处理的问题。可以说throw引发了异常
  2. try语句块(try block)。异常处理部分使用了try语句块处理异常。try语句块以try开始,并以一个或者多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理。catch子句“处理”异常,因此也将他们称作异常处理代码。
  3. 一套异常类,用于在throw表达式和相关catch子句之间传递异常的具体信息。

c++定义了一组标准异常类,用于报告标准库函数遇到的问题,这些异常类也可用于用户编写的程序中,他们分别包含在4个头文件中:

  • exception头文件定义了最通用的异常类exception.它只报告异常的发生,不提供任何信息;
  • stdexcept头文件定义了几种常见的异常类;
  • new头文件中定义了bad_alloc异常类型;
  • type_info头文件定义了bad_cast类型。

stdexcept文件中定义的异常

异常意义
exception最常见的问题
runtime_error只有在运行时才能检测出来的问题
range_error运行时错误:生成的结果超出了有意义的值域范围
overflow_error运行时错误:计算上溢
underflow_error运行时错误:计算下溢
logic_error程序逻辑错误
domain_error逻辑错误:参数对应的结果值不存在
invalid_argument逻辑错误:无效参数
length_error逻辑错误:试图创建一个超出类型最大长度的对象
out_of_range逻辑错误:使用一个超出有效范围的值

exception、bad_alloc和bac_cast对象不允许为这些对象提供初始值,只能默认初始化
其他异常类型则相反,应该使用string对象或者C风格字符串初始化,不允许使用默认初始化的方式。
所有异常类型都只定义了一个名为what的成员函数,无参,返回一个指向C风格字符串的const char*

测试代码:

#include <iostream>
#include <new>
#include <stdexcept>

using namespace std;

int exception_test(int i) {
  if (i == 0) throw runtime_error("just test exception test");
  if (i == 1) throw exception();
  if (i == 2) throw bad_alloc();
  if (i == 3) throw logic_error("logical error");
}

int main() {
  for (int i = 0; i < 4; ++i) {
    try {
      exception_test(i);
    } catch (runtime_error e) {
      std::cout << e.what() << std::endl;
    } catch (bad_alloc e) {
      std::cout << e.what() << std::endl;
    } catch (exception e) {
      std::cout << e.what() << std::endl;
    }
  }
  return 0;
}
just test exception test
std::exception
std::bad_alloc
std::exception

不能第一个catch exception ,否则后续异常捕获不到。如果将上述代码18与22行互换,则输出如下:

std::exception
std::exception
std::exception
std::exception

这里可以用exception来捕获任何标准异常,自己定义的异常如果继承自exception,则应该也可以,但具体不清楚。
这里catch的参数如果是基类型,则可以派生类进行初始化,如果为非引用类型,则派生类被切成基类,如上述所示,如果使用基类的引用,则类似于函数参数方式,参数以常规方式绑定到异常类中。因此上述代码可以简化为:

#include <iostream>
#include <new>
#include <stdexcept>

using namespace std;

int exception_test(int i) {
  if (i == 0) throw runtime_error("just test exception test");
  if (i == 1) throw exception();
  if (i == 2) throw bad_alloc();
  if (i == 3) throw logic_error("logical error");
}

int main() {
  for (int i = 0; i < 4; ++i) {
    try {
      exception_test(i);
    } catch (exception &e) { // 注意这里参数变成了引用
      std::cout << e.what() << std::endl;
    }
  }
  return 0;
}

输出:

just test exception test
std::exception
std::bad_alloc
logical error

在这里插入图片描述

异常重新抛出

有时,单独一个catch语句不能完整处理一个异常。在执行了一段校正操作后,当前的catch语句决定将由调用链更上一层的函数接着处理,该catch可以通过重新抛出(rethrowing)的操作将异常传递给另外一个catch。这里重新抛出仍然是一条throw语句,只不过不包含任何表达式:

     throw;

空的throw语句只能出现在catch语句或者catch语句直接或间接调用的函数之内,如果在处理代码之外遇到了空throw语句,编译器将调用terminate结束整个程序。

捕获所有异常的处理代码\

catch(...)

上述语句可以捕获所有异常。通常与重新抛出语句一起使用。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值