【C++ 学习 ㉟】- 异常详解

目录

一、C++ 异常处理的基本语法

1.1 - 抛出异常

1.2 - 检测和捕获异常

二、在函数调用链中异常栈展开的匹配原则

三、异常重新抛出

四、异常规范

五、C++ 标准异常体系


程序的错误大致可以分为以下三种:

  1. 语法错误:在编译和链接阶段就能发现,只有符合语法规则的代码才能生成可执行程序。语法错误是最容易发现、最容易定位、最容易排除的错误,程序员最不需要担心的就是这种错误。

  2. 逻辑错误:编写的代码不能够达到预期的效果,这种错误可以通过调试来解决。

  3. 运行时错误:指程序在运行期间发生的错误,例如除数为 0、内存分配失败、数组下标越界、文件不存在等,如果不能发现这些错误并加以处理,很可能会导致程序崩溃。C++ 异常机制就是为了解决运行时错误而引入的


一、C++ 异常处理的基本语法

1.1 - 抛出异常

C++ 通过 throw 关键字抛出异常,语法为:

throw exceptionData;

exceptionData 可以是任意类型的异常数据

示例:

int division(int a, int b)
{
    if (b == 0)
        throw "Division by zero condition!";
    else
        return a / b;
}

1.2 - 检测和捕获异常

检测和捕获异常的语法为:

try {
    // 可能抛出异常的代码
}
catch (exceptionType1 e1) {
    // 处理异常的代码
}
...
catch (exceptionTypeN eN) {
    // 处理异常的代码
}

try...catch 语句的执行过程是:执行 try 块中的语句(称作检测异常),如果执行过程中没有异常抛出,那么所有 catch 块中的语句都不会被执行;如果执行过程中抛出了异常,那么抛出异常后会立即跳转到第一个异常类型和抛出的异常类型匹配的 catch 块,并执行其中的语句(称作捕获异常)

注意

  1. catch 可以有多个,但至少要有一个

  2. catch(...) 可以捕获任意类型的异常

  3. 可以使用基类捕获派生类对象

  4. 如果不希望处理异常数据,可以将 e1、...、eN 省略掉

示例:

#include <iostrea>
using namespace std;
​
class Base { };
class Derived : public Base { };
​
int main()
{
    try {
        throw Derived();
        cout << "This statement will not be executed." << endl;
    }
    catch (Base) {
        cout << "Exception type::Base" << endl;
    }
    catch (Derived) {
        cout << "Exception type::Derived" << endl;
    }
    catch (...) {
        cout << "Unknow exception" << endl;
    }
    // Exception type::Base
    return 0;
}


二、在函数调用链中异常栈展开的匹配原则

  1. 当异常被抛出后,首先检查 throw 语句是否在 try 块内部,如果在,则查找匹配的 catch 块

  2. 如果没找到匹配的 catch 块,则退出当前函数栈,继续在调用该函数的函数栈中查找匹配的 catch 块

  3. 如果到达 main 函数栈,依旧没有找到匹配的 catch 块,则终止程序

上述这个沿着函数调用链查找匹配的 catch 块的过程称为栈展开

#include <iostream>
using namespace std;
​
int division(int a, int b)
{
    if (b == 0)
        throw "Division by zero condition!";
    else
        return a / b;
}
​
void func()
{
    int a = 0, b = 0;
    cin >> a >> b;
    cout << division(a, b) << endl;
}
​
int main()
{
    try {
        func();
    }
    catch (const char* errmsg) {
        cout << errmsg << endl;
    }
    catch (...) {
        cout << "Unknow exception" << endl;
    }
    return 0;
}


三、异常重新抛出

单个 catch 块有可能不能完全处理一个异常,在进行一些校正处理后,希望将异常交给更外层的调用函数来处理,那么在 catch 块中就可以将异常重新抛出

#include <iostream>
using namespace std;
​
int division(int a, int b)
{
    if (b == 0)
        throw "Division by zero condition!";
    else
        return a / b;
}
​
void func()
{
    int* arr = new int[10];
    try {
        int a = 0, b = 0;
        cin >> a >> b;
        cout << division(a, b) << endl;
    }
    catch (...) {
        delete[] arr;
        cout << "func : delete[] finished" << endl;
        throw;  // 异常重新抛出
    }
    delete[] arr;
}
​
int main()
{
    try {
        func();
    }
    catch (const char* errmsg) {
        cout << errmsg << endl;
    }
    catch (...) {
        cout << "Unknow exception" << endl;
    }
    return 0;
}

throw; 没有指明抛出什么类型的异常,因此抛出的就是 catch 块捕获到的异常,这个异常会被 main 函数中的 catch 块捕获


四、异常规范

throw 关键字除了可以用在函数体中抛出异常,还可以用在函数头和函数体之间,指明当前函数能够抛出的异常类型,这称为异常规范

void func() throw(int);

这条语句声明了一个名为 func 函数,它的返回值类型为 void,参数列表为空,并且只能抛出 int 类型的异常,如果抛出其他类型的异常,try 将无法捕获,只能终止程序

如果函数会抛出多种类型的异常,那么可以用逗号隔开

void func() throw(int, char, double);

如果函数不会抛出任何任何异常,那么 () 中什么也不写

void func() throw();
// C++ 中新增的 noexcept 关键字,表示不会抛出异常
void func() noexcept;

此时,func() 函数就不能抛出任何类型的异常了,即使抛出了,try 也检测不到

·


五、C++ 标准异常体系

C++ 语言本身或者标准库中抛出的异常都是 exception 的子类,称为标准异常

exception 类位于 <exception> 头文件中,它被声明为:

class exception {
public:
    exception () throw();
    exception (const exception&) throw();
    exception& operator= (const exception&) throw();
    virtual ~exception() throw();
    virtual const char* what() const throw();
}

下图展示了 exception 类的继承层次:

实际上,很多公司都会自定义自己的异常体系进行规范的异常管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/128930.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<蓝桥杯软件赛>零基础备赛20周--第5周--杂题-2

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…

Java,多线程,线程的两种创建方式

首先是多线程的一些相关概念&#xff1a; 相关概念&#xff1a; 程序&#xff08;program&#xff09;&#xff1a;为完成特定任务&#xff0c;用某种语言编写的一组指令的集合。即指一段静态&#xff08;指不在执行中&#xff09;的代码。 进程&#xff08;process&#xf…

Qt QTableWidget表格的宽度

默认值 QTableWIdget的表格宽度默认是一个给定值&#xff0c;可以手动调整每列的宽度&#xff0c;也不填满父窗口 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {this->resize(800,600);QStringList contents{"11","111111111111",&…

聊聊模板引擎<Template engine>

模板引擎是什么 模板引擎是一种用于生成动态内容的工具&#xff0c;通常用于Web开发中。它能够将静态的模板文件和动态数据结合起来&#xff0c;生成最终的HTML、XML或其他文档类型。模板引擎通过向模板文件中插入变量、条件语句、循环结构等控制语句&#xff0c;从而实现根据…

操作系统:输入输出管理(一)系统概述与设备独立性软件

一战成硕 5.1 I/O系统概述5.1.1 I/O设备5.1.2 I/O控制方式5.1.3 I/O软件层次结构5.1.4 应用程序的I/O接口 5.2 设备独立性软件5.2.1 与设备无关的软件5.2.2 高速缓存与缓冲区5.2.3 设备分配与回收5.2.4 spooling技术&#xff08;假脱机技术&#xff09; 5.1 I/O系统概述 5.1.1…

一分钟秒懂人工智能对齐

文章目录 1.什么是人工智能对齐2.为什么要研究人工智能对齐3.人工智能对齐的常见方法 1.什么是人工智能对齐 人工智能对齐&#xff08;AI Alignment&#xff09;指让人工智能的行为符合人的意图和价值观。 人工智能系统可能会出现“不对齐”&#xff08;misalign&#xff09;…

【EI会议征稿】JPCS独立出版-第五届新材料与清洁能源国际学术会议(ICAMCE 2024)

JPCS独立出版-第五届新材料与清洁能源国际学术会议&#xff08;ICAMCE 2024&#xff09; 2024 5th International Conference on Advanced Material and Clean Energy 第五届新材料与清洁能源国际学术会议&#xff08;ICAMCE 2024&#xff09;将于2024年2月23-25日在中国▪长沙…

电机应用-无刷直流电机

无刷直流电机 无刷直流电机&#xff08;Brushless Dirent Current Motor&#xff0c;简称BLDCM&#xff09;由电动机主体和驱动器组成&#xff0c;无电刷和无换向器&#xff0c;是除了有刷电机外用得最多的一种电机。 无刷直流电机不使用机械的电刷装置&#xff0c;采用方波自控…

带你一分钟看懂 “kubernetes”

目录 什么是 Kubernetes Kubernetes 概述 为什么需要 Kubernetes&#xff0c;它能做什么&#xff1f; 什么是 Kubernetes 从官方网站上可以看到&#xff0c;它是一个工业级的容器编排平台。Kubernetes 这个单词是希腊语&#xff0c;它的中文翻译是“舵手”或者“飞行员”。在…

NFT Insider112:Gucci Cosmos LAND亮相 The Sandbox,和YGG一起探索Web3增长新方式

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members(https://twitter.com/WHALEMembers)、BeepCrypto&#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周…

0基础制作产品图册的干货,一个网站即可

很多朋友想要制作产品图册&#xff0c;但是不知道如何入手&#xff0c;其实制作产品图册并不难&#xff0c;一个网站就可以搞定。下面就为大家分享一些干货&#xff0c;帮助大家快速入门。 首先&#xff0c;我们需要选择一个合适的网站。比如FLBOOK在线制作电子杂志平台。这个网…

【chat】3: ubutnu 安装mysql-8

如何在 Ubuntu 20.04 上安装 MySQLC搭建集群聊天室&#xff08;七&#xff09;&#xff1a;MySQL数据库配置 及项目工程目录配置 大神是centos的. apt 安装 rootk8s-master-2K4G:~# sudo apt install mysql-server Reading package lists... Done Building dependency tree Re…

SQL触发器

触发器是与表有关的数据库对象。 在insert/update/delete之前(BEFORE)或之后(AFTER)&#xff0c;触发并执行触发 器中定义的SQL语句集合。 触发器的这种特性可以协助应用在数据库端确保数据的完整性, 日志记录 , 数据校验等操作 。 使用别名OLD和NEW来引用触发器中发生变化的…

Google play提高上包率——如何防止封号、拒审、下架?

Google Play是全球最大的移动应用商店之一&#xff0c;它是运行Android操作系统的设备的官方应用商店。它提供各种数字内容&#xff0c;包括应用程序&#xff08;应用&#xff09;、游戏、音乐、书籍等&#xff0c;包括免费和付费选项。这也为许多游戏/APP出海的企业或开发者提…

国内首批!华为云云原生中间件DCSDMS获软件可信“卓越级”认证

11月6日&#xff0c;在软件供应链可信研讨大会上&#xff0c;工业和信息化部电子第五研究所&#xff08;以下简称“电子五所”&#xff09;发布了首批软件产品可信评估结果&#xff0c;并为通过评估的企业颁发证书。 华为云作为中国领先的综合云计算服务商受邀参加本次大会&…

【星海随笔】git的使用

1.在终端&#xff0c;检查git是否安装 git --version 2.没有安装的话去&#xff0c;官网&#xff0c;下载git 3.一直点下一步即可 4.安装后在终端检查git是否安装好 5.设置用户名和邮件地址(最好和GitHub的用户名/邮箱保持一致) git config --global user.name “自己的用户名”…

建表时如何合理选择字段类型

前言 我们在建表的时候关于字段类型的选择会有这么几类人&#xff1a; 严谨型 严格调研每个字段可能的大小&#xff0c;然后根据不同字段类型的限制&#xff0c;进行选择&#xff0c;这一类人在创建关系型数据表的时候是没有问题的。图自己省事型 把所有字段都设置为String&a…

100 寻找重复数

寻找重复数 题解1 二分法题解2 快慢指针(同环形链表2(ab)(ab)kL) 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返…

使用Pytorch的一些小细节(一)

文章目录 前言数据结构-张量max函数索引函数赋值函数拼接函数 前言 由于不经常动手写代码&#xff0c;所以对于python语言中的常见数据结构的用法也不是很熟悉&#xff0c;对于pytorch中的数据结构就更加不熟悉了。之前的代码基础是基于C语言的&#xff0c;属性都是自己定义&a…

动态规划-构建乘积数组

** 描述 给定一个数组 A[0,1,…,n-1] ,请构建一个数组 B[0,1,…,n-1] ,其中 B 的元素 B[i]A[0]A[1]…*A[i-1]A[i1]…*A[n-1]&#xff08;除 A[i] 以外的全部元素的的乘积&#xff09;。程序中不能使用除法。&#xff08;注意&#xff1a;规定 B[0] A[1] * A[2] * … * A[n-1…
最新文章