C++之异常处理

news2025/1/12 21:04:58

异常

异常是面向对象语言处理错误的一种方式。当一个函数出现自己无法处理的错误时,可以抛出异常,然后输的直接或者间接调用者处理这个错误。

语法

捕获全部的异常

try
{
    //可能抛出异常的代码
    //throw异常对象
}
catch(...)
{
    //不管什么异常,都在这里统一处理
}

捕获指定的异常

try
{
    // 可能抛出异常的代码。
    // throw 异常对象;
}
catch (exception1 e)
{
    // 发生exception1异常时的处理代码。
}
catch (exception2 e)
{
   // 发生exception2异常时的处理代码。
}

在try语句块中,如果没有发生异常,执行完try语句块中的代码后,将继续执行try语句块之后的代码;如果发生了异常,用throw抛出异常对象异常对象的类型决定了应该匹配到哪个catch语句块如果没有匹配到catch语句块,程序将调用abort()函数中止。

如果try语句块中用throw抛出异常对象,并且匹配到了catch语句块,执行完catch语句块中的代码后,将继续执行catch语句块之后的代码,不会回到try语句块中。

如果程序中的异常没有被捕获,程序将异常中止。

catch是通过throw抛出的对象匹配的;
catch(...)可以捕获任意类似的对象,主要捕获自己都不知道的异常;

下面看几个例子

  1. try语句块中代码出现异常

#include<iostream>
#include<exception>
#include<array>
using namespace std;
void test()
{
    array<int, 5> a = { 1,2,3,4,5 };
    //try
    //{
    //    int a1 = a[5];
    //    cout << a1 << endl;
    //}
    //catch(exception e)
    //{
    //    cout << "1越界了" << endl;
    //}
    try
    {
        int a2 = a.at(5);
        cout << a2 << endl;
    }
    catch (exception e)
    {
        cout << "2越界了" << endl;
    }
}
int main()
{
    test();
    return 0;
}

这里由于第一个数组越界程序直接崩溃,注释掉,运行,结果如下

因为at会检查是否越界,当访问越界时会抛出异常,从而catch发挥作用。

  1. try语句中抛出异常

#include<iostream>
#include<exception>
#include<array>
using namespace std;
void test1()
{
    try
    {
        throw"未知错误";
        cout << "语句1" << endl;
    }
    catch (const char* e)
    {
        cout << e << endl;
    }
}
int main()
{
    test1();
    return 0;
}

我们发现try语句块中throw后面的语句没有执行,我们继续观察

  1. try语句中的函数抛出异常

#include<iostream>
#include<exception>
#include<array>
using namespace std;
void func()
{
    throw"未知错误!";
    cout << "func()中" << endl;
}
void test2()
{
    try
    {
        func();
        cout << "try中" << endl;
    }
    catch (const char* e)
    {
        cout << e << endl;
    }
}
int main()
{
    test2();
    return 0;
}

这里我们发现try语句中抛出异常函数后面的语句和函数体抛出语句后面的语句没有执行。

这是为什么呢??

在函数调用链中异常展开匹配原则

1. 首先检查 throw 本身是否在 try 块内部,如果是再查找匹配的 catch 语句,如果有匹配的,则调到catch的地方进行处理;
2. 没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch;
3. 如果到达main函数的栈,依旧没有匹配的,则终止程序。上述这个沿着调用链查找匹配的catch子句的 过程称为 栈展开,也称栈解旋。所以实际中我们最后都要加一个catch(…)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
4. 找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
#include<iostream>
#include<exception>
using namespace std;
void func1()
{
    throw"多级函数调用的未知错误";
}
void func2()
{
    func1();
}
void func3()
{
    func2();
}
void test3()
{
    try
    {
        func3();
        cout << "try中" << endl;
    }
    catch (...)
    {
        cout << "未知错误" << endl;
    }
}
int main()
{
    test3();
    return 0;
}

总结:没有找到匹配的函数栈就会被释放。

把上述代码进行修改如下

#include<iostream>
#include<exception>
using namespace std;
void func1()
{
    throw"多级函数调用的未知错误";
    
}
void func2()
{
    try
    {
        func1();
    }
    catch(const char* e)
    {
        cout << e << endl;
    }
    
}
void func3()
{
    func2();
}
void test3()
{
    try
    {
        func3();
        cout << "try中" << endl;
    }
    catch (...)
    {
        cout << "未知错误" << endl;
    }
}
int main()
{
    test3();
    return 0;
}

多级catch

下面给出例子

#include<iostream>
using namespace std;
int main()
{
    cout << "1-错误A,2-错误B,other-未知错误" << endl;
    cout << "请输入:";
    int x = 0;
    while (cin >> x)
    {
        try
        {
            if (x == 1)
                throw"错误A";
            else if (x == 2)
                throw"错误B";
            else
                throw"未知错误";
        }
        catch(const char* e)
        {
            cout << e << endl;
        }
        cout << "请输入:";
    }
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java之动态规划之子序列问题

目录 0.动态规划问题 一.最长递增子序列 1.题目描述 2.问题分析 3.代码实现 二.最长递增子序列 1.题目描述 2.问题分析 3.代码实现 三.最长重复子数组 1.题目描述 2.问题分析 3.代码实现 4.代码的优化(滚动数组) 四.最长公共子序列 1.题目描述 2.问题分析 3.代…

C语言学习笔记(五):数组的使用

数组的定义 数组是一组有序数据的集合。数组中各数据的排列是有一定规律的&#xff0c;下标代表数据在数组中的序号。 用数组名和下标即可唯一地确定数组中的元素。 数组中的每一个元素都属于同一个数据类型。 一维数组 定义与引用 int a[10] {0,1,2,3,4,5,6,7,8&#xf…

Matlab绘制隐函数总结-二维和三维

1.二维隐函数 二维隐函数满足f(x,y)0f(x,y)0f(x,y)0&#xff0c;这里无法得到yf(x)yf(x)yf(x)的形式。不能通过普通函数绘制。 我们要关注的是使用fplot函数和fimplicit函数。 第1种情况&#xff1a;基本隐函数 基本的隐函数形式形如&#xff1a; x2y22x2(x2y2)12x^{2}y^{…

【Qt】Qt 隐式共享

文章目录一、导读二、隐式共享简介三、源码角度分析隐式共享四、隐式共享在开发中的使用五、隐式共享迭代器问题六、隐式共享类和线程一、导读 在实际开发中&#xff0c;Qt中很多类可以直接作为函数参数传递&#xff0c;这样做是为了什么&#xff1f;其背后的实现机制又是什么…

进程,线程

进程是操作系统分配资源的基本单位&#xff0c;线程是CPU调度的基本单位。 PCB&#xff1a;进程控制块&#xff0c;操作系统描述程序的运行状态&#xff0c;通过结构体task,struct{…}&#xff0c;统称为PCB&#xff08;process control block&#xff09;。是进程管理和控制的…

#电子电气架构——Vector工具常见问题解决三板斧

我是穿拖鞋的汉子,魔都中一位坚持长期主义的工科男。 今天在与母亲聊天时,得到老家隔壁邻居一位大姐年初去世的消息,挺让自己感到伤感!岁月如流水,想抓都抓不住。想起平时自己加班的那个程度,可能后续也要自己注意身体啦。 老规矩,分享一段喜欢的文字,避免自己成为高知…

千锋教育嵌入式物联网教程之系统编程篇学习-03

目录 进程的终止 exit函数 _exit函数 进程退出清理 进程间的替换 进程间通信 常见通信机制 进程间通信的实质 信号 产生信号的方式 信号的默认处理方式 进程对信号的处理方式 kill函数 进程的终止 使用exit函数对进程进行终止&#xff0c;而return只是结束函数&a…

电子技术——共模抑制

电子技术——共模抑制 我们在之前学习过&#xff0c;无论是MOS还是BJT的差分输入对&#xff0c;共模信号并不会改变漏极电流的大小&#xff0c;因此我们说差分输入对共模信号无响应。但是实际上由于各种客观非理想因素&#xff0c;例如电流源有限阻抗等&#xff0c;此时共模是影…

LINUX提权入门手册

前言 发点存货 LINUX权限简介 在学习提权之前我们先了解一下linux里面的权限我们使用命令: ls -al即可查看列出文件所属的权限&#xff1a; 文件头前面都有一段类似的字符&#xff0c;下面我们仔细分析一下里面符号分别代表什么。 -rw-r--r-- 1 root root 第一个符号-的…

现代 cmake (cmake 3.x) 操作大全

cmake 是一个跨平台编译工具&#xff0c;它面向各种平台提供适配的编译系统配置文件&#xff0c;进而调用这些编译系统完成编译工作。cmake 进入3.x 版本&#xff0c;指令大量更新&#xff0c;一些老的指令开始被新的指令集替代&#xff0c;并加入了一些更加高效的指令/参数。本…

MongoDB--》MongoDB数据库以及可视化工具的安装与使用—保姆级教程

目录 数据库简介 MongoDB数据库的安装 MongoDB数据库的启动 MongoDB数据库环境变量的配置 MongoDB图形化管理工具 数据库简介 在使用MongoDB数据库之前&#xff0c;我们应该要知道我们使用它的原因&#xff1a; 在数据库当中&#xff0c;有常见的三高需求&#xff1a; Hi…

如何手写一个springboot starter?

本文主要分享了如何手写一个spring starter&#xff0c;把你的代码作为jar包进行开源。命名规则&#xff08;不要使用spring-boot开头&#xff0c;以避免将来spring-boot官方使用你的starter而重名&#xff09;官方命名格式为&#xff1a;spring-boot-starter-xxx非官方命名格式…

ucos-ii 的任务调度原理和实现

ucosii 任务调度和原理1、ucos-ii 任务创建与任务调度 1.1、任务的创建 当你调用 OSTaskCreate( ) 进行任务的创建的时候&#xff0c;会初始化任务的堆栈、保存cpu的寄存器、创建任务的控制块&#xff08;OS_TCB&#xff09;等的操作&#xff1b; if (OSTCBPrioTbl[prio] (OS_…

Python中如何书写文件路径

当程序运行时&#xff0c;变量是保存数据的好方法&#xff0c;但变量、序列以及对象中存储的数据是暂时的&#xff0c;程序结束后就会丢失&#xff0c;如果希望程序结束后数据仍然保持&#xff0c;就需要将数据保存到文件中。Python 提供了内置的文件对象&#xff0c;以及对文件…

数据库 delete 表数据后,磁盘空间为什么还是被一直占用?

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 最近有个上位机获取下位机上报数据的项目&#xff0c…

计算机网络6:Http协议

目录HTTP1.基本概念1.1.1 URI2. 请求和响应报文2.1.请求报文2.2.响应报文3.HTTP报文实现细节3.1响应头主要字段3.2HTTP状态码3.3 HTTP方法3.3.1 GET方法3.3.2 HEAD3.3.3 POST3.3.4 PUT3.3.5 PATCH3.3.6 DELETE3.3.7 OPTIONS3.3.8 CONNECT3.4 HTTP首部&#xff08;头部&#xff…

【MT7628】开发环境搭建-Fedora12安装之后无法上网问题解决

1.按照如下图所示,打开Network Connections 2.点击Network Connections,弹出如下界面

面向对象程序(C++)设计基础

一、类&对象C 在 C 语言的基础上增加了面向对象编程&#xff0c;C 支持面向对象程序设计。类是 C 的核心特性&#xff0c;通常被称为用户定义的类型。类提供了对象的蓝图&#xff0c;所以基本上&#xff0c;对象是根据类来创建的。声明类的对象&#xff0c;就像声明基本类型…

面试题(二十二)消息队列与搜索引擎

2. 消息队列 2.1 MQ有什么用&#xff1f; 参考答案 消息队列有很多使用场景&#xff0c;比较常见的有3个&#xff1a;解耦、异步、削峰。 解耦&#xff1a;传统的软件开发模式&#xff0c;各个模块之间相互调用&#xff0c;数据共享&#xff0c;每个模块都要时刻关注其他模…

Grafana 系列文章(十五):Exemplars

Exemplars 简介 Exemplar 是用一个特定的 trace&#xff0c;代表在给定时间间隔内的度量。Metrics 擅长给你一个系统的综合视图&#xff0c;而 traces 给你一个单一请求的细粒度视图&#xff1b;Exemplar 是连接这两者的一种方式。 假设你的公司网站正经历着流量的激增。虽然…