13、C++异常处理

news2024/11/29 4:29:41

13、c++异常处理

  • 抛出异常
  • 捕获异常
  • 未抛出异常时的流程
  • 抛出异常时的流程
  • 捕获异常
  • 匹配顺序
  • 异常说明
  • 异常处理
  • 构造函数中的异常
  • 析构函数中的异常
  • 标准库异常类

抛出异常

  • throw 异常对象
  • 可以抛出基本类型的对象,如:throw -1;throw "内存分配失败!";
  • 也可以抛出类类型的对象,如:MemoryException ex;throw ex;throw MemoryException();
  • 但不要抛出局部对象的指针,如:MemoryException ex;throw &ex; // 错误!

捕获异常

try {
可能引发异常的语句
}
catch (异常类型1& ex){针对异常类型1的异常处理;}
catch (异常类型2& ex) {针对异常类型2的异常处理;}
...
catch (异常类型n& ex) {针对异常类型n的异常处理;}

未抛出异常时的流程

在这里插入图片描述

抛出异常时的流程

在这里插入图片描述

捕获异常

  • 建议在catch子句中使用引用接收异常对象,避免因为拷贝构造带来性能损失
  • 推荐以匿名临时对象的形式抛出异常
  • 异常对象必须允许被拷贝构造和析构

匹配顺序

根据异常对象的类型自上至下顺序匹配,而非最优匹配,因此对子类类型异常的捕获不要放在对基类类型异常的捕获后面

异常说明

异常说明是函数原型的一部分,旨在说明函数可能抛出的异常类型
返回类型 函数名(形参表) throw (异常类型1,异常类型2,...) {函数体;}

异常说明是一种承诺,承诺函数不会抛出异常说明以外的异常类型
如果函数抛出了异常说明以外的异常类型,那么该异常将无法被捕获并导致进程中止

隐式抛出异常的函数也可以列出它的异常说明

异常说明可以没有也可以为空

  • 没有异常说明,表示可能抛出任何类型的异常
    • void foo (void) { ... }
  • 异常说明为空,表示不会抛出任何类型的异常
    • void foo (void) throw () { ... }

异常说明在函数的声明和定义中必须保持严格一致,否则将导致编译错误

异常处理

  • 可以抛出基本类型的异常
  • 可以抛出类类型的异常
  • 利用类类型的异常,携带更多诊断信息,以便查错
  • 可以在catch块中继续抛出所捕获的异常,或其它异常
  • 任何未被捕获的异常,默认的处理方式就是中止进程
  • 忽略异常,不做处理

构造函数中的异常

构造函数可以抛出异常,某些时候还必须抛出异常

  • 构造过程中可能遇到各种错误,比如内存分配失败
  • 构造函数没有返回值,无法通过返回值通知调用者

构造函数抛出异常,对象将被不完整构造,而一个被不完整构造的对象,其析构函数永远不会被执行

  • 所有对象形式的成员变量,在抛出异常的瞬间,都能得到正确地析构 (构造函数的回滚机制)
  • 所有动态分配的资源,必须在抛出异常之前,自己手动释放,否则将形成资源的泄漏

析构函数中的异常

不要从析构函数中主动抛出异常

在两种情况下,析构函数会被调用

  • 正常销毁对象,离开作用域或显式delete
  • 在异常传递的堆栈辗转开解(stack-unwinding)过程中

对于第二种情况,异常正处于激活状态,而析构函数又抛出了异常这时C++将通过std::terminate()函数,令进程中止
对于可能引发异常的操作,尽量在析构函数内部消化
try {... }catch (...) { ... }

标准库异常类

在这里插入图片描述

// 利用return报告异常信息
#include <iostream>
#include <cstdio>
using namespace std;

class A{
public:
    A() {  cout << "A()被调用" << endl; }
    ~A(){  cout << "~A()被调用" << endl; }
};


void foo(){
    cout << "foo出错前的几百行代码" << endl;
    A a;
    FILE* pfile = fopen("./cfg","r");
    if(!pfile)
        throw -1;
    cout << "foo出错后的几百行代码" << endl;
} // a.~A() 释放a本身所占内存空间

void bar(){
    cout << "bar出错前的几百行代码" << endl;
    A b;
//    try{
        foo();
//    }
//    catch(int e){
//        cout << "bar函数中捕获异常信息: " << e << endl;
//    }
    cout << "bar出错后的几百行代码" << endl;
} // b.~A() 释放b本身所占内存空间

void hum(){
    cout << "hum出错前的几百行代码" << endl;
    A c;
    try{
        bar();
    }
    catch(int e){
        cout << "hum函数中捕获异常信息:" << e << endl;
    }
    cout << "bar出错后的几百行代码" << endl;
} // c.~A() 释放c本身所占内存空间


int main( void ){
    cout << "main出错前的几百行代码" << endl;
    A d;
    hum();
    cout << "main出错后的几百行代码" << endl;
    return 0;
} // d.~A() 释放d本身所占内存空间

// 建议将子类类型异常捕获放到基类类型异常捕获的前面
#include <iostream>
using namespace std;

class A{};

class B : public A{};



void foo(){
    throw B();
}

int main( void ){
    try{
        foo();
    }
    catch(B& b){  
        cout << "B类型catch捕获" << endl;
    }
    catch(A& a){  
        cout << "A类型catch捕获" << endl;
    }
    return 0;
} 

// 没有异常说明和异常说明为空
#include <iostream>
using namespace std;

void foo()  { // 没有异常说明:函数内部可能抛出任何类型的异常
    throw  "Hello world!"; // 3.14; // -1;
}

void bar() throw(){ // 异常说明为空:承诺函数内部绝对不会抛出任何类型的异常
//  throw -1;
}
// 异常说明在声明和定义时必须严格一致,否则将报编译错误
void hum() throw(int,double);  // 声明
void hum() throw(int,double){ // 定义
}




int main( void ){
    try{
       foo();
//     bar();
    }
    catch( ... ){ // 忽略异常
        // ...
    }

/*    catch(int& e){
        cout << "1. 捕获异常信息:"<< e << endl; 
    }
    catch(double& e){
        cout << "2. 捕获异常信息:" << e << endl;
    }
    catch(const char* e){
        cout << "3. 捕获异常信息:" << e << endl;
    }*/
    return 0;
} 

// 构造函数中的异常
#include <iostream>
#include <cstdio>
using namespace std;

class A{
public:
    A(){ cout << "A()被调用" << endl; }
    ~A(){ cout << "~A()被调用" << endl; }
};
class C{
public:
    C():m_p(new int){
        //【A m_a;】定义m_a,利用m_a.A()
        //【int* m_p = new int;】定义m_p,初值指向一块堆内存(动态资源)
        cout << "C()被调用" << endl;
        FILE* pfile = fopen("./cfg","r");
        if(!pfile){
            delete m_p; // 需要自己手动释放
            // 对于m_a.利用m_a.~A()
            // 释放m_a/m_p本身所占内存空间
            throw -1;
        }
        // ....构造函数中后续代码...
    }
    ~C(){
        delete m_p;
        cout << "~C()被调用" << endl;
        // 对于m_a.利用m_a.~A()
        // 释放m_a/m_p本身所占内存空间
    }
private:
    A m_a;
    int* m_p;
};


int main( void ){
    try{
        C c; // 定义c,利用c.C();
    }// 如果c是完整构造对象,将利用c.~C(),但是如果c是残缺对象,就不会调用~C()
    catch( ... ){
        // ...
    }
    return 0;
} 

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

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

相关文章

【C语言:动态内存管理】

文章目录 前言1.malloc2.free3.calloc4.realloc5.动态内存常见错误6.动态内存经典笔试题分析7.柔性数组8.C/C中的内存区域划分 前言 文章的标题是动态内存管理&#xff0c;那什么是动态内存管理&#xff1f;为什么有动态内存管理呢&#xff1f; 回顾一下以前学的知识&#xff…

C++ Core Guidelines解析 ( 好书推荐 )

C Core Guidelines是Bjarne和 Herb Sutter发起编写的一个开源项目&#xff0c;汇聚了 C社区多年来积累的宝贵经验&#xff0c;是非常全面的编程最佳实践指导&#xff0c;包括代码风格、函数、类、错误处理、性能优化等&#xff0c;可以说是C社区的集大成者。用Effective Modern…

电脑主板支持的cpu型号汇总

一、如何选择不同的主板和对应CPU 1、看针脚&#xff1a;网上有相应的参数&#xff0c;只要CPU能安装到主板中&#xff0c;基本就兼容&#xff0c;这主要取决CPU插槽和主板插槽十分一致。 2、看型号&#xff1a;桌面处理器&#xff0c;只有Intel和AMD两大平台&#xff0c;他们对…

dToF直方图之美_deadtime死区时间

上节在激光雷达多目标测距中有个问题为什么激光雷达不用做pile up算法,有人会有疑问,我看过很多人的简历,都把pile up量产校正算法写为最为自豪重要的算法攻坚,可能会吸引一波人的眼球。这要是在两三年前是值得被肯定的,但是如今随着dToF非常多量产项目落地,pile up研究不…

【Hive】——安装部署

1 MetaData&#xff08;元数据&#xff09; 2 MetaStore &#xff08;元数据服务&#xff09; 3 MetaStore配置方式 3.1 内嵌模式 3.2 本地模式 3.3 远程模式 4 安装前准备 <!-- 整合hive --><property><name>hadoop.proxyuser.root.hosts</name><v…

BUUCTF-[GYCTF2020]FlaskApp flask爆破pin

这道题不需要爆破也可以getshell ssti都给你了 {{((lipsum.__globals__.__builtins__[__import__](so[::-1])[popen]("\x63\x61\x74\x20\x2f\x74\x68\x69\x73\x5f\x69\x73\x5f\x74\x68\x65\x5f\x66\x6c\x61\x67\x2e\x74\x78\x74")).read())}} 但是学习记录一下pin…

ETLCloud详解,如何实现最佳实践及问题排查

ETLCloud介绍 ETLCloud是新一代全域数据集成平台&#xff0c;领先于市场同类产品的数据集成平台(DataOps)&#xff0c;只需单击几下即可完成数据清洗转换、传输入仓等操作&#xff0c;具备高效、智能、一站式的全域数据集成优势&#xff0c;如&#xff1a; 毫秒级实时数据同步 …

MMLM之Gemini:《Introducing Gemini: our largest and most capable AI model》的翻译与解读

MMLM之Gemini&#xff1a;《Introducing Gemini: our largest and most capable AI model》的翻译与解读 导读&#xff1a;2023年12月6日&#xff0c;Google重磅发布大规模多模态模型Gemini&#xff0c;表示了Google语言模型发展到了一个新阶段&#xff0c;其多模态和通用能力明…

力扣1445 连续字符

目录 ​编辑 题目 示例 示例1 示例2 提示 详细解读 题目 给你一个字符串 s &#xff0c;字符串的「能量」定义为&#xff1a;只包含一种字符的最长非空子字符串的长度。 请你返回字符串 s 的 能量。 解题思路 这个问题的解法相对比较简单&#xff0c;可以通过遍历字…

int(1) 和 int(10) 的区别

int(1) 和 int(10) 的区别 最近遇到个问题&#xff0c;有个表的要加个user_id字段&#xff0c;user_id字段可能很大&#xff0c;于是我提mysql工单alter table xxx ADD user_id int(1)。领导看到我的sql工单&#xff0c;于是说&#xff1a;这int(1)怕是不够用吧&#xff0c;接…

Python finally-资源回收

有些时候&#xff0c;程序在 try 块里打开了一些物理资源&#xff08;例如数据库连接、网络连接和磁盘文件等&#xff09;&#xff0c;这些物理资源都必须被显式回收。 Python 的垃圾回收机制不会回收任何物理资源&#xff0c;只能回收内存中对象所占用的内存。 那么在哪里回收…

【智能家居】八、监控摄像采集、人脸识别比对进行开门功能点

一、使用 fswebcam 测试 USB 摄像头 二、根据demo来实现功能点 三、功能点编写编译运行实现 一、使用 fswebcam 测试 USB 摄像头 a. 安装 fswebcam orangepiorangepi:~$ sudo apt update orangepiorangepi:~$ sudo apt-get install -y fswebcamb. 安装完 fswebcam 后可以使用…

036.Python面向对象_self_cls_super

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

AMC8美国数学竞赛历年真题集在线练习操作指南和2024年备考建议

今天是2023年12月10日&#xff0c;距离2024年的AMC8美国数学竞赛的举办还有40天时间。据六分成长了解&#xff0c;有一些孩子报名参加了AMC8的机构培训班系统学习&#xff0c;也有一些孩子选择了自己自学备考。 有家长问AMC8的培训是否一定要参加机构的培训班学习&#xff1f;…

Aho Corasick Algorithm

文章目录 前言介绍实现参考 前言 Aho Corasick Algorithm又叫AC自动机&#xff0c;该算法是一个匹配算法&#xff0c;用来匹配文本Text中多个patterns分别出现的次数&#xff1b; 我们定义n为patterns的总长度&#xff1b;m为Text的长度&#xff1b; 问题&#xff1a;在ahis…

C语言算法与数据结构,旅游景区地图求最短路径

背景&#xff1a; 本次作业要求完成一个编程项目。请虚构一张旅游景区地图&#xff0c;景区地图包括景点&#xff08;结点&#xff09;和道路&#xff08;边&#xff09;&#xff1a;地图上用字母标注出一些点&#xff0c;表示景点&#xff08;比如&#xff0c;以点 A、B、C、…

【C语言】字符串函数strcpystrcatstrcmpstrstr的使⽤和模拟实现

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 ✏️真正相信奇迹的家伙&#xff0c;本身和奇迹一样了不起啊&#xff01; 欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;>希望看完我的文章对你有小小的帮助&am…

聚类算法的性能度量

聚类算法的性能度量 聚类算法就是根据数据中样本与样本之间的距离或相似度&#xff0c;将样本划分为若干组&#xff0f;类&#xff0f;簇&#xff0c;其划分的原则&#xff1a;簇内样本相似、簇间样本不相似&#xff0c;聚类的结果是产生一个簇的集合。 其划分方式主要分为两…

前后端联调神器《OpenAPI-Codegen》

在后端开发完接口之后&#xff0c;前端如果再去写一遍接口来联调的话&#xff0c;会很浪费时间&#xff0c;这个时候使用OpenAPI接口文档来生成Axios接口代码的话&#xff0c;会大大提高我们的开发效率。 Axios引入 Axios是一个基于Promise的HTTP客户端&#xff0c;用于浏览器…

leetcode每日一题39

122.买卖股票的最佳时机II 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] j0 不持有股票 j1持有股票 i&#xff1a;第i天 dp[i][j]&#xff1a;第i天&#xff0c;持有状态为j时的最大现金确定递推公式 dp[i][0]max(dp[i-1][0], dp[i-1][1]prices[i]); 第…