C++异常处理

        C++ 异常处理涉及到三个关键字:try、catch、throw。 在 c++程序中,任何需要检测异常的语句,都必须在 try 语句块中执行,异常必须由紧跟着 try 语句后面的 catch 语句来捕获并处理,因此 try 与 catch 总是结合使用,下面是它们的语法
throw 异常类型;try
{//try 语句块
}
catch(类型 n 参数 n)
{//异常处理语句
}
throw 是用来抛出异常的,它抛出的异常类型可以是普通类型也可以是聚合类型。
基本类型:int、char、float
聚合类型:指针、数组、字符串、结构体
例如:
int init()
{int fd=open("1.txt",O_RDWR);if(fd==-1){throw "打开失败"; //抛出字符串类型异常}char buf[128];int rd=read(fd,buf,128);if(rd==-1){throw 1.88; //抛出浮点型类型异常}return 1;
}
        可以看到当程序出错时,就可以使用 throw 抛出不同异常类型,用以进行不同错误处理。
try 是用来检测抛出的错误的,例如:
try
{//下面两个函数可能会抛出异常int a = init();copyDir();
}
        通常,把可能会抛出异常的函数对象都包含在 try 中做检测。
而 catch 就是用来对抛出的错误进行判断和处理的,它必须在 try 的后面。
try
{int a=init();cout<<a<<endl;
}
catch(const char* na)
{cout<<na<<endl;
}
catch(float b)
{cout<<b<<endl;
}
catch(...) 
{cout<<"其他情况"<<endl;
}
        catch 会判断 try 检测到的异常的类型,根据类型开发者可以对其进行不同的处理(备注:C++
中…在 catch 中的作用相当于 default)

throw 的异常规范写法

        throw 关键字除了可以用在函数体中抛出异常,还可以用在函数头和函数体之间,指明当前函数能够抛出的异常类型,这称为异常规范(Exception specification)
第一种:例如:
double func ( char param ) throw ( int );
        声明了一个名为 func 的函数,它的返回值类型为 double,有一个 char 类型的参数,并且只能抛出 int 类型的异常。如果抛出其他类型的异常,try 将无法捕获,只能终止程序。
第二种:例如:
double func ( char param ) throw ( int , char , exception );
        函数可抛出多种类型的异常,用逗号隔开
第三种:例如:
double func ( char param ) throw ();
        如果函数不会抛出任何异常,那么( )中什么也不写,如此,func() 函数就不能抛出任何类型的异常了,即使抛出了,try 也检测不到。
        但是异常规范是 C++98 新增的一项功能,但是后来的 C++11 已经将它抛弃了,不再建
议使用,嘻嘻。

exception 异常类

        C++ 语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的异常。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。 之所以使用引用,是为了提高效率。如果不使用引用,就要经历一次对象拷贝(要调用拷贝构造函数)的过程。

        上面就是 std 中包含的一些异常类型,它们都是继承 exception 而来的,例如当使用了无效的参数时,就会抛出一个 std::invalid_argument 的错误,而程序开发者其实要定义新的异常类型时,可以继承 exception 类来做处理。

        上图是系统中 bad_alloc 异常类型的由来,可以看到他也是继承 exception 而来的,由此示例,当我们想要其他类型的异常处理的时,我们也可以根据上图的方法去继承一个新异常类型,例
如:
#include <iostream>
using namespace std;struct MyException : public exception
{const char* what() const throw (){return "C++ Exception";}
};int main() 
{try{throw MyException();}catch (MyException & e){std::cout << e.what() << std::endl;}catch (std::exception & e){//其他的错误}return 0;
}
        MyException 就是我们新创建的一个异常类型,当遇到一些相应的错误时,我们就可以返回这个异常类型,然后在这个异常类型的成员函数 what 中写入我们的错误处理提示。

异常层次

        同一个 try 语句块可以对应多个 catch 语句块,catch 语句块可以定义具体处理的异常类型,不同的类型的异常由不同的 catch 语句块处理;
        try 语句块可以抛出任何类型的异常,catch(...)用于处理所有类型的异常,任何异常都只能被捕获一次;
        throw 抛出的异常必须被 catch 处理,如果当前函数能够处理异常,继续执行;如果当前函 数不能处理异常,函数停止执行并返回;
        未被处理的异常会顺着函数调用栈向上传递,直到被处理为止,否则程序将停止执行。

noexcept 关键字

在上面说道在 C++11 之前,表示函数是否会抛出异常是通过在函数后面加入 throw 来说明的,具体查看 上面的异常规范,但是在 C++11 之后,就一般使用 noexcept 关键字来修饰函数是否会抛出异常了。
int close_t ( int s ) noexcept ;
        例如上面表名 close_t 函数绝对不会抛出异常,这是第一种形式,就是直接在函数后面加入
noexcept 关键字来表名函数绝对不会抛出异常,接下来看第二种。
int close_t ( int x , int y ) noexcept ( 1 > 0 )
{
        return 0 ;
}
        在 noexcept 后面可以加上一个常量表达式,表达式的值只能是 true 或 false,当为 true 时其作用就和直接写 noexcept 的效果是一样的,表明不会抛出异常,当为 false 的时候表明可能会抛出
异常。
最常用的就是就是用 noexcept 当运算符配合第二种方式进行,例如:
int fun()
{return 1;
}
int close_t(int x,int y) noexcept(noexcept(fun()))
{return 0;
}
        上面 fun()函数如果不抛出异常那么 noexcept(fun())就会返回 true,就相当于表明 close_t 也 不会抛出异常,使得两个函数的异常抛出情况相同。
或:
int close_t(int x,int y) noexcept(noexcept(x>y))
{return 0;
}
上面则是常用的根据函数参数情况来指定函数是否会抛出异常。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++并发编程实战——05.内存模型与原子操作

文章目录 内存模型与原子操作内存模型原子操作和原子类型标准原子类型std::atomic_flagstd::atomic\<bool>std::atomic<T\*>std::atomic<user_define_type> 类模板非成员函数 同步操作和强制排序同步发生与先行发生内存序**顺序一致性**(memory_order_seq_cs…

图解系列--路由器和它庞大的功能

03.01 何为路由器 路由器是指主要负责 OSI参考模型中网络层的处理工作&#xff0c;并根据路由表信息在不同的网络 之间转发IP 分组的网络硬件(图3-1)。这里的网络一般是指IP 子网&#xff0c;也可以称为广播域。此外&#xff0c;现在的路由器还会搭载其他各种各样的功能。 0…

【Midjourney入门教程3】写好prompt常用的参数

文章目录 1、图片描述词&#xff08;图片链接&#xff09;文字描述词后缀参数2、权重划分3、后缀参数版本选择&#xff1a;--v版本风格&#xff1a;--style长宽比&#xff1a;--ar多样性: --c二次元化&#xff1a;--niji排除内容&#xff1a;--no--stylize--seed--tile、--q 4、…

openeuler 使用指令查找U盘:输入fdisk -l,内核崩溃 ,系统重启,使用lsblk显示正常,数据传输正常

报错日志&#xff1a; [rootedgenode1 ~]# fdisk -l Disk /dev/ram0: 4 MiB, 4194304 bytes, 8192 sectors Units: sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disk /d…

数据结构与算法:使用数组模拟队列Java版

逻辑分析 代码实现 package com.haimeng.queue;import java.util.Scanner;public class ArrayQueueDemo {public static void main(String[] args) {//测试一把//创建一个队列ArrayQueue queue new ArrayQueue(3);char key ; //接收用户输入Scanner scanner new Scanner(S…

web3 在React dapp中全局管理web3当前登录用户/智能合约等信息

上文 Web3 React项目Dapp获取智能合约对象我们在自己的前端dapp项目中链接获取到了 自己的智能合约 我们继续 我们还是先启动ganache环境 终端输入 ganache -d然后发布一下我们的智能合约 打开我们的合约项目 终端输入 truffle migrate --reset这样 我们的智能合约就部署到区…

L1和L2正则化通俗理解

机器学习中&#xff0c;如果参数过多&#xff0c;模型过于复杂&#xff0c;容易造成过拟合&#xff08;overfit&#xff09;。即模型在训练样本数据上表现的很好&#xff0c;但在实际测试样本上表现的较差&#xff0c;不具备良好的泛化能力。为了避免过拟合&#xff0c;最常用的…

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板

一、购买域名并且进行备案和解析&#xff0c;正常情况下&#xff0c;购买完域名&#xff0c;如果找不到去哪备案&#xff0c;可以在腾讯云上搜索“备案”关键词就会出现了&#xff0c;所以这里不做详细介绍&#xff0c;直接进行步骤提示&#xff1a; 二、申请ssl证书&#xff0…

LeetCode算法题解|​ 669. 修剪二叉搜索树​、108. 将有序数组转换为二叉搜索树、​538. 把二叉搜索树转换为累加树​

一、LeetCode 669. 修剪二叉搜索树​ 题目链接&#xff1a;669. 修剪二叉搜索树 题目描述&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变…

比亚迪今年的薪资。。

大家或许已经对比亚迪在西安的宣讲会有所耳闻&#xff0c;那场面真的是座无虚席。如果你稍微迟到了一些&#xff0c;那么你可能只能在门外或是走廊听了。 事实上&#xff0c;许多人早早地抵达了&#xff0c;只要稍微晚到&#xff0c;就可能错过了室内的位置。 更令人震惊的是&…

SpringBoot----自定义Start(自定义依赖)

一&#xff0c;为什么要定义Start 向阿里云OSS如果我们要引入的话很麻烦&#xff0c;所以我们可以自定义一些组件&#xff0c; 然后我们只需要在pom文件中引入对应的坐标就可以 二&#xff0c;怎么定义&#xff08;以阿里云OSS为例&#xff09; 1&#xff0c; 定义两个组件模块…

自学SLAM(6)相机与图像实践:OpenCV处理图像与图像拼接(点云)

前言 如果写过SLAM14讲第一次的作业&#xff0c;或者看过我之前的运行ORB_SLAM2教程应该都安装过OpenCV了&#xff0c;如果没有安装&#xff0c;没关系&#xff0c;可以看我之前的博客&#xff0c;里面有如何安装OpenCV。 链接: 运行ORB-SLAM2&#xff08;含OpenCV的安装&…