异常(C++)

异常

  • 前言
  • 一、程序的错误分类
  • 二、异常
    • 1. 概念
    • 2. 捕获异常的关键字和格式
    • 3. 异常的使用
      • 异常的原则
      • 异常再抛出
      • 异常说明
      • 注意事项
    • 4. 自定义异常体系
    • 5. C++标准库的异常体系
  • 三、总结

前言

  1. 在程序运行时经常碰到一些错误,例如年龄、身高不能为负,除数为0等,这些错误放到程序中如果不加以管制,程序就会崩溃。C++提供了异常机制,让我们能跟捕获运行时错误,给程序一次机会,给用户一个反馈。
  1. C++异常处理机制可以让我们捕获并进行处理错误,然后我们可以通过捕获后的判断,重新给程序指一条明路,或者在程序结束之前,做一些必要的工作,例如将错误写到日志等。

说到C++,C语言的处理错误方式也简单提一下:
assert宏

  1. 生产环境可能被禁用(会带来性能开销,并且不能对用户提供任何实际好处)编译器会优化掉。
  2. 开发环境可以用来检查条件,但是不提供详细的错误信息,并且终止程序。
  3. 只能用来检查布尔表达式,无法用于更复杂的逻辑和错误处理。

返回错误码

  1. 程序员要自己查找对应的错误,系统很多库函数也都是通过错误码(errno)表示错误

一、程序的错误分类

程序的错误大致可以分为三种,分别时语法错误、逻辑错误和运行时错误。

  1. 语法错误:在编译和链接阶段就能发现,必须全符合语法规则才能生成可执行代码。这种错误最简单。
  2. 逻辑错误:编码思路问题,执行的结果不是预定的,也可以通过调试解决。
  3. 运行时错误:程序运行期间发生的错误,如同除0,越界等。C++异常(Exception)机制就是为了解决这种错误。

二、异常

1. 概念

异常:异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛异常,让函数的直接或间接调用者处理这个错误。

2. 捕获异常的关键字和格式

C++异常处理涉及三个关键字

  • throw:出现问题,程序使用throw抛出异常
  • catch:有抛出也得有捕获,catch关键字就是用来捕获异常。捕获的地方就是处理问题的地方。
  • try:try块中的代码为保护代码,如果出错会激活特定的异常,后面跟着一个或多个catch块。

eg:语法

try{//保护区,就是可能会出错的代码
}
catch(ExceptionName e1){//出错后,通过异常处理程序捕获异常,在这里处理问题或者 再抛出
}
catch(ExceptionName e2){//因为异常对象类型的多样,所以可以多个catch块捕获匹配的异常
}
catch(...){//如果try块中出现异常,而前面的catch块也没有捕获,这是最后一道防线,所有类型都会在这里捕获,但不知道异常的错误原因。
}

注意: 可能有些不好理解,后面内容我会逐步介绍

3. 异常的使用

异常的原则

简单的例子:

double Division(int a, int b)
{if (b == 0)throw "Division by zero condition!";elsereturn (double)a / (double)b;
}void Func()
{int len, time;cin >> len >> time;cout << Division(len, time) << endl;
}int main()
{try {Func();}catch (const char* errmsg){cout << errmsg << endl;}catch (...){cout << "unknow exception" << endl;}return 0;
}

异常 栈调用
调用链

上例的函数调用链中栈的细节:

  1. 检查被throw是否在try块中,如果在并触发异常。
  2. 被throw抛出对象的类型和最近的catch块的参数进行匹配,匹配成功,则调到catch块中处理。没有匹配成功,则退出当前函数栈,在调用该函数的栈中继续匹配。
  3. 如果到main函数的栈依旧没有匹配,则终止程序(非正常结束)。但一般有catch(…)兜底。
  4. 如果匹配到catch子句处理完块中内容后,会沿着try,catch语句后继续执行

匹配原则

  1. throw抛出的对象类型与调用链中位置最近并且参数类型一样的catch匹配。
  2. throw抛出异常会生成一个异常对象的拷贝(因为抛出的对象可能是一个临时对象),这个拷贝的对象会被catch以后销毁。(类似函数传值返回)
  3. catch(…)可以捕获任意类型异常,但是不知道异常错误是什么。
  4. 匹配原则的例外:可以抛出派生类对象,使用基类捕获。(后面讲)

异常再抛出

一个单独的catch语句不能完整的处理某个异常,再执行一些校正操作之后,可能会抛给调用链更上一层的函数接着处理异常。
这个简单的校正工作可能就是改变参数内容,但是这里又要注意是不是引用
eg:

//简单的校正操作
catch (my_error& eObj){                     //引用类型 eObj.status = errCodes::severeErr;      //修改了异常对象throw;
}
catch (other_error eObj) {                     //非引用类型 eObj.status = errCodes::severeErr;         //只修改了异常对象的局部副本throw;
}

异常再抛出:

try
{//保护代码//...
}
catch (const char* errmsg)
{cout << errmsg << endl;
}
catch (...)
{throw;//异常再抛出,不含任何表达式//注意异常进行抛出后,是直接跳过这个函数栈的后面部分,例如下面的打印语句就  不会在进行执行cout << "unknow Exception" << endl;
}

异常说明

目的是为了让使用者知道该函数抛出的异常类型。

异常说明:

//这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void func()  throw(A, B, C, D);//这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size) throw (std::bad_alloc);//这里表示这个函数不会抛出异常
void* operator delete (std::size_t size, void* ptr) throw ();//若无异常接口声明:表示这个函数可以抛出任何类型的异常
void func1()

C++11新增的noexcept,表示不会抛出异常

void recoup(int) noexcept; //不会抛出异常
void alloc(int)            //可能抛出异常

注意: noexcept的位置也很特殊,因为const,final,override或者虚函数=0,都可以跟在函数后面,所以noexcept要在const及引用限定符之后,在final,override或者虚函数=0之前。

注意事项

建议

  1. 不要在构造函数中抛出异常(可能导致对象未完成初始化)
  2. 不要在析构函数中抛出异常(可能导致资源泄漏)
  3. 不要在lock和unlock之间抛异常(死锁)(后面的博客讲)

4. 自定义异常体系

实际很多公司会自己定义异常体系,规范管理。大家抛出的都是继承的派生类对象,捕获一个基类即可。

继承体系

eg:服务器开发中使用的异常继承体系(例子)

class Exception
{
public:Exception(const string& errmsg, int id):_errmsg(errmsg),_id(id){}virtual string what() const{return _errmsg;}protected:string _errmsg;int _id;
};class SqlException : public Exception
{
public:SqlException(const string& errmsg, int id, const string& sql):Exception(errmsg, id), _sql(sql){}virtual string what() const{string str = "SqlException:";str += _errmsg;str += "->";str += _sql;return str;}private:const string _sql;
};class CacheException : public Exception
{
public:CacheException(const string& errmsg, int id):Exception(errmsg, id){}virtual string what() const{string str = "CacheException:";str += _errmsg;return str;}
};class HttpServerException : public Exception
{
public:SqlException(const string& errmsg, int id, const string& type):Exception(errmsg, id), _type(type){}virtual string what() const{string str = "HttpServerException:";str += _type;str += ":";str += _errmsg;return str;}private:const string _type;
};

调用捕获:

void SQLMgr()
{srand(time(0));if (rand() % 7 == 0){throw SqlException("权限不足", 100, "select * from name = '张三'");}//throw "xxxxxx";
}void CacheMgr()
{srand(time(0));if (rand() % 5 == 0){throw CacheException("权限不足", 100);}else if (rand() % 6 == 0){throw CacheException("数据不存在", 101);}SQLMgr();
}void HttpServer()
{// ...srand(time(0));if (rand() % 3 == 0){throw HttpServerException("请求资源不存在", 100, "get");}else if (rand() % 4 == 0){throw HttpServerException("权限不足", 101, "post");}CacheMgr();
}int main()
{while (true){Sleep(500);      //引用系统头文件<Windows.h>try {HttpServer();}catch (const Exception& e) // 这里捕获父类对象就可以{// 多态cout << e.what() << endl;}catch (...){cout << "Unkown Exception" << endl;}}return 0;
}

5. C++标准库的异常体系

C++标准库的异常体系
注意: C++标准库的异常体系设计的不好用,所以一般都是定义自己的异常体系

三、总结

异常总体而言利大于弊

异常的优缺点

优点:

  1. 异常对象定义好了,可以更加清晰准确的展示出错误的各种信息,更好的定位bug。
  2. 不需要层层返回检查并错误码,异常体系直接跳到catch捕获的位置
  3. 很多第三方库都包含异常,想要使用这些库也需要使用异常
  4. 部分函数使用异常更好处理,例如没有返回值的或者不便于返回的。

缺点:

  1. 执行流乱跳,导致跟踪调试时以及分析程序困难,很混乱
  2. 性能的开销
  3. C++标准库的异常体系定义的不好,大家各自定义异常体系,不统一

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

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

相关文章

sql注入 [GXYCTF2019]BabySQli1

打开题目 多次尝试以后我们发现存在一个admin的账号&#xff0c;但是密码我们不知道 我们尝试一下万能密码 admin or 11 -- q 报错 我们尝试bp抓一下包看看 看着很像编码 先去base32解码 再base64解码 得到 我们从这个sql语句中得到注入点为name 根据报错信息我们知道是…

网络安全(一)--网络环境构成,系统的安全

2. 网络攻防环境 目标 了解攻防环境构成了解入侵检测系统&#xff08;平台&#xff09;的部署位置 2.1. 环境构成 2.1.1. 环境框图 一个基本的网络攻防实验环境包括&#xff1a;靶机、攻击机、入侵检测分析系统、网络连接四部分组成。 一个基础的网络攻防实验环境需要如下…

阿里云租赁费用_阿里云服务器多配置报价表

阿里云服务器租用费用&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、轻量应用服务器2核2G3M带宽轻量服务器一年87元&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;ECS云服务器e系列2核2G配置99元一年、2核4G配置365元一年、2核8G配置522元一年…

Git多人协作(一)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 由于博主是一个人&#xff0c;所以博主为完成这篇文章&#xff0c;在Linux下克隆了一个仓库&#xff0c;在windows下克隆了一个仓库&#xff0c;以此来模拟多人协作开发。而实际开发中&#xff0c;每个人都有自己的git…

【CSP】202305-1_重复局面Python实现

文章目录 [toc]试题编号试题名称时间限制内存限制题目背景问题描述输入格式输出格式样例输入样例输出样例说明子任务提示Python实现 试题编号 202305-1 试题名称 重复局面 时间限制 1.0s 内存限制 512.0MB 题目背景 国际象棋在对局时&#xff0c;同一局面连续或间断出现3次或3…

python3安装lifelines

目录 一、环境 二、安装lifelines 出现问题 三、测试导入 一、环境&#xff1a; jupyter notebook中新建ipynb文件 二、安装lifelines pip install --upgrade --no-deps githttps://github.com/CamDavidsonPilon/lifelines.git出现问题&#xff1a; 缺少模块autograd、f…

sqlite3.44.2的编译

文章目录 sqlite3.44.2的编译概述笔记解决shell.c编译报错的方法整理 - 正常可用的编译脚本过程剩下的事情验证编译出的输出是否可以给工程正常使用?END sqlite3.44.2的编译 概述 想从源码编译一份Sqlite3.44.2出来. 编译sqlite3.44.2前置需要的TCL环境已经编译出来到了, 做…

学习Python能给我们带来什么?有什么帮助?

文章目录 前言学习Python能做什么1、抓取各类数据、文本等信息2、批量清洗和处理数据3、提供可视化工具4、进行深度学习 Python的用途有哪些普通人学习python有什么好处关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python…

Linux挂载配置本地yum源

1.vi /etc/yum.repos.d/redhat.repo 2. [baseos] namebaseos baseurlfile:///mnt/BaseOS #enabled:默认为1 enabled1 gpgcheck0 [appstream] nameappstream baseurlfile:///mnt/AppStream enabled1 gpgcheck0 3. mount /dev/sr0 /mnt/ 4.yum clean all 5.yum makecache

神秘鸭是如何让你的手机控制你的电脑的?

神秘鸭 神秘鸭即是一个应用&#xff0c;它能让手机语音助手、智能音箱变的更为强大&#xff01;通过神秘鸭&#xff0c;您的手机语音助手、智能音箱可以用来控制电脑、智能家居、DIY的物联网设备。 支持的手机、平板品牌 Apple 华为 小米 三星 OPPO VIVO 一加 当然不代表仅支…

SpringBoot 知识梳理

学习目标 掌握基于 SpringBoot 框架的程序开发步骤熟练使用基于 SpringBoot 配置信息修改服务器配置基于 SpringBoot 的完成 SSM 整合项目开发 1 SpringBoot 简介 1.1 入门案例 1.1.1 步骤 ① &#xff1a;创建新模块&#xff0c;选择 Spring 初始化&#xff0c;并配置模块…

Doris 编译报错 Error: flex version (2.5.37) must be greater than or equal to 2.6.0

Doris 编译过程报错 Error: flex version (2.5.37) must be greater than or equal to 2.6.0yum update flex 不生效 下载flex 安装包 https://github.com/westes/flex/releases解压 tar -xvf flex-2.6.4.tar

万宾科技智能水环境综合治理监测系统效果

水环境综合治理是一项旨在全面改善水环境质量的系统工程。它以水体为对象&#xff0c;综合考虑各种因素&#xff0c;通过科学规划和技术手段&#xff0c;解决水环境污染、生态退化等问题&#xff0c;核心理念是“统一规划、分步实施&#xff1b;标本兼治&#xff0c;重在治本&a…

Mendix版的电商京东首页长什么样儿?

前言 世界需要大前端。大前端需要Mendix。 近日经常有企业IT侧的朋友反应&#xff0c;自家需要一个神奇的内容管理平台&#xff0c;来快速打造随需应变的公司官网&#xff0c;亦或企业官微&#xff0c;如果能在小程序里呈现产品营销类的功能更好。首先要肯定的是&#xff0c;…

Spring Cache【娓娓道来】

目录​​​​​​​ 1.自我介好&#x1f633;&#x1f633;&#x1f633; 2.常用注解 &#x1f495;&#x1f495;&#x1f495; 3.EnableCaching&#x1f926;‍♂️&#x1f926;‍♂️&#x1f926;‍♂️ 4.CachePut&#x1f937;‍♀️&#x1f937;‍♀️&#x1f93…

Python 从入门到精通 学习笔记 Day01

Python 从入门到精通 第一天 今日目标 计算机组成原理、编程语言、Python环境安装 第一个Python程序、PyCharm的安装与使用 Python的基础语法、Python的基本数据类型 一、计算机组成原理 计算机的组成 计算机硬件通常由以下几个部分组成: 1.中央处理器(CPU):负责执行计算机…

windows建立软链 报 无法将“mklink”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

当我执行网上提供的mklink 的时候&#xff0c;出现 mklink : 无法将“mklink”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。怎么回事&#xff0c;原来&#xff0c;要在执行的签名加 cmd /c 当我执行建立软链接时&#xff0c;提示 没有足够的权限&#xff0c;要用管理…

SE考研真题总结(一)

本帖开始分享考研真题中设计【软件工程】的部分&#xff0c;预计会出5期左右&#xff0c;敬请期待~ 一.单选题 1.程序编写不是软件质量保障过程~ 静态代码扫描是今年来多数被人提及的软件应用安全解决方案之一&#xff0c;指程序员在编写好代码后无需进行编译&#xff0c;直接…

【数据结构】—红黑树(C++实现)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 &#x1f49c;本文前置知识&#xff1a; AVL树 ♈️今日夜电波&#xff1a;Letter Song—ヲタみん 1:36━━━━━━️&#x1f49f;──────── 5:35 …

基于SpringBoot的大学活动平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着互联网技术的不断…