C++学习---异常处理机制

news2024/11/26 13:31:50

文章目录

  • 前言
  • abort()函数 and 返回错误码的异常方式
  • C++异常处理机制
    • 异常的类别
      • what()函数

前言


abort()函数 and 返回错误码的异常方式

在说C++异常处理机制之前,了解一下abort()函数和返回错误码的异常处理。

Abort( )函数的原型位于头文件cstdlib(或stdlib.h)中,其典型实现是向标准错误流(即cerr使用的错误流)发送消息abnormal program termination(程序异常终止),然后终止程序。

其部分实现代码:

在这里插入图片描述

运行程序后,输入 10 和 -10 会返回错误信息,“”

在这里插入图片描述

注意使用abort()函数的话是直接终止程序,而不是返回main()函数。

比abort()函数更灵活的办法是使用返回错误码的形式来指出异常问题。

可使用指针参数引用参数来将值返回给调用程序,并使用函数的返回值来指出成功还是失败。

实例:

#include <iostream>
#include <cfloat>

bool hmean(double a, double b, double *ans);

int main()
{
    double x, y, z;

    std::cout << "Enter two numbers: ";
    while (std::cin >> x >> y)
    {
        if (hmean(x, y, &z))
            std::cout << "Harmonic mean of " << x << " and " << y
            << " is " << z << std::endl;
        else   
            std::cout << "One value should not be the negative "
                << "of the other - try again.\n";
            std::cout << "Enter next set of numbers <q to quit>: ";
    }
    std::cout << "Bye!\n";
    return 0;
}

bool hmean(double a, double b, double *ans)
{
    if (a == -b)
    {
        *ans = DBL_MAX;
        return false;
    }
    else
    {
        *ans = 2.0 * a * b / (a + b);
        return true;
    }
}

运行结果:

在这里插入图片描述


C++异常处理机制

C++提供了一种异常处理机制,允许程序在运行时出现错误时抛出异常,并在适当的位置捕获和处理这些异常。

C++的异常处理通常会涉及到三个关键字:throwtrycatch

  • throw:异常抛出,当程序发生错误或异常情况时,可以使用 throw 语句来抛出异常;异常可以是标准类型(如整数或字符串)或自定义类型。
throw SomeException("An error occurred");

  • try、catch:异常捕获,在 try 块中放置可能引发异常的代码,然后在一个或多个 catch 中捕获并处理异常,每个 catch 块可以捕获不同种类的异常。
try {
    // 可能引发异常的代码
} catch (SomeException& ex) {
    // 处理 SomeException 异常
} catch (AnotherException& ex) {
    // 处理 AnotherException 异常
}

一个示例:

#include <iostream>
double hmean(double a, double b);

int main()
{
    double x, y, z;

    std::cout << "Enter two numbers: ";
    while (std::cin >> x >> y)
    {
        try {
            z = hmean(x, y);
        }
		catch (const char *s)
        {
            std::cout << s << std::endl;
            std::cout << "Enter a new pair of numbers: ";
            continue;
        }
        std::cout << "Harmonic mean of " << x << " and " << y
        << " is " << z << std::endl;
        std::cout << "Enter next set of numbers <q to quit>: ";
    }
    std::cout << "Bye!\n";
    return 0;
}

double hmean(double a, double b)
{
    if (a == -b)
        throw "bad hmean() arguments: a = -b not allowed";
    return 2.0 * a * b / (a + b);
}

运行结果:

在这里插入图片描述

上述程序中,try块中是可能引发异常的代码,catch块中是对异常的处理。

执行throw语句类似于执行返回语句,因为它也将终止函数的执行;但throw不是将控制权返回给调用程序,而是导致程序沿函数调用序列后退,直到找到包含try块的函数。

接下来看将10和−10传递给hmean( )函数后发生的情况。
If语句导致hmean( )引发异常。这将终止hmean( )的执行。程序向后搜索时发现,hmean( )函数是从main( )中的try块中调用的,因此程序查找与异常类型匹配的catch块。程序中唯一的一个catch块的参数为char*,因此它与引发异常匹配。程序将字符串“bad hmean( )arguments: a = -b not allowed”赋给变量s,然后执行处理程序中的代码。处理程序首先打印s——捕获的异常,然后打印要求用户输入新数据的指示,最后执行continue语句,命令程序跳过while循环的剩余部分,跳到起始位置。

在这里插入图片描述

如果 没有触发异常,就不会进入catch块,程序回执行catch后的第一条语句。如上面实例输入 1和2后的结果。


异常的类别

throw关键字用于抛出一个异常,通常是在检测到错误或异常情况时,你可以抛出任何类型的数据,通常是一个对象,但也可以是基本数据类型,如整数。

如:

if (condition) {
        throw MyException("Something went wrong");
    }

在上述中,如果condition满足的话,就会抛出一个自定义异常**MyException**,然后在catch块中捕获异常。

在执行 throw 语句时,throw 表达式的值会被复制构造为一个新的异常对象。这个异常对象包含有关异常的信息,例如类型和其他相关数据。

异常的类别:异常可以分为不同的类别,这些类别通常是派生自 std::exception 类的自定义异常类,但也可以使用内置的异常类,如 int(整数异常)。

在C++中提供了一系列标准的异常,定义在 中,我们可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的,如下所示:
在这里插入图片描述

下表是对上面层次结构中出现的每个异常的说明:
在这里插入图片描述

一个使用了std::logic_error类别的示例:

#include <iostream>
#include <stdexcept>

int divide(int numerator, int denominator) {
    if (denominator == 0) {
        throw std::logic_error("Division by zero is not allowed");
    }
    return numerator / denominator;
}

int main() {
    try {
        int result = divide(10, 2);
        std::cout << "Result: " << result << std::endl;
        
        result = divide(10, 0); // 引发逻辑错误异常
        std::cout << "Result: " << result << std::endl; // 这一行不会执行
    } catch (const std::logic_error& ex) {
        std::cerr << "Logic error caught: " << ex.what() << std::endl;
    }

    return 0;
}

输出结果:
在这里插入图片描述

除了使用C++提供的异常类别外,我们也可以自定义异常,例如throw中的MyException;

我们可以定义一个名为MyException的自定义异常类,它继承自std::exception

class MyException : public std::exception {
public:
    MyException(const char* message) : message_(message) {}

    const char* what() const noexcept override {
        return message_.c_str();
    }

private:
    std::string message_;
};

在上述代码中,public中 有个构造函数MyException, const char* message表示接收一个字符串指针,存放到后面的message_成员变量中。
接着重写了 what()函数,它返回一个指向异常消息的const char*指针。what()函数被标记为const noexcept override,表示它是一个虚函数,不会引发异常,而且是不可更改的。

完整代码如下:

#include <iostream>
#include <stdexcept>

class MyException : public std::exception {
public:
    MyException(const char* message) : message_(message) {}

    const char* what() const noexcept override {
        return message_.c_str();
    }

private:
    std::string message_;
};

int divide(int numerator, int denominator) {
    if (denominator == 0) {
        throw MyException("Custom Exception: Division by zero is not allowed");
    }
    return numerator / denominator;
}

int main() {
    try {
        int result = divide(10, 2);
        std::cout << "Result: " << result << std::endl;

        result = divide(10, 0); // 引发自定义异常
        std::cout << "Result: " << result << std::endl; // 这一行不会执行
    } catch (const MyException& ex) {
        std::cerr << "Custom Exception caught: " << ex.what() << std::endl;
    }

    return 0;
}

what()函数

关于what()函数:

what()函数是C++中异常类的一个成员函数,用于返回一个描述异常的人类可读的错误消息。通常,在自定义异常类中,你可以重写what()函数以提供有关异常的详细信息。在标准的std::exception类及其派生类中,what()函数已经被实现,以返回一个默认的错误消息。

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

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

相关文章

CSS关于默认宽度

所谓的默认宽度&#xff0c;就是不设置width属性时&#xff0c;元素所呈现出来的宽度 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><style>* {margin: 0;padding: 0;}.box {/…

git 生成公钥

1、通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t ed25519 -C "Gitee SSH Key" 三次回车 2、查看生成的 SSH 公钥和私钥&#xff1a; ls ~/.ssh/ 3、把公钥设置到git id_ed25519.pub 4、测试 ssh -T gitgitee.com 成功&#xff01;&#xff01;&…

基于减法平均算法的无人机航迹规划-附代码

基于减法平均算法的无人机航迹规划 文章目录 基于减法平均算法的无人机航迹规划1.减法平均搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用减法平均算法来优化无人机航迹规划。 …

朋友圈延迟评论,你用过吗?

在社交媒体时代&#xff0c;朋友圈已经成为人们交流和互动的重要平台。然而&#xff0c;在发表评论时&#xff0c;我们往往会被情绪冲昏头脑&#xff0c;或者因为时间紧迫而没有充分思考。这可能会导致一些不恰当的言论&#xff0c;或者错过一些更精准的表达方式。朋友圈延迟评…

摄像头内参准确性验证方法

前言 摄像头内参标定出来后&#xff0c;标定结果是否准确&#xff1f;有些内参准确性的验证方案需要很大的场地&#xff0c;且有很多误差源不好控制&#xff08;特别是对视野比较大的摄像头&#xff09;&#xff0c;惠州市华阳数码特电子有限公司发明了一种占用场地小测试精度…

uniapp u-tabs表单如何默认选中

首先先了解该组件&#xff1b;该组件&#xff0c;是一个tabs标签组件&#xff0c;在标签多的时候&#xff0c;可以配置为左右滑动&#xff0c;标签少的时候&#xff0c;可以禁止滑动。 该组件的一个特点是配置为滚动模式时&#xff0c;激活的tab会自动移动到组件的中间位置。 …

【Java初阶习题】 -- 类和对象

目录 1.局部变量必须先初始化才能使用2. this的两种用法3. import语句不能导入一个指定的包4.代码块的执行顺序5.静态变量的调用6 . 现有一个Data类&#xff0c;内部定义了属性x和y&#xff0c;在main方法中实例化了Data类&#xff0c;并计算了data对象中x和y的和。 1.局部变量…

11月第1周榜单丨飞瓜数据B站UP主排行榜榜单(B站平台)发布!

飞瓜轻数发布2023年10月30日-11月5日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数、带货数据等维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营…

【分布式事务】深入探索 Seata 的四种分布式事务解决方案的原理,优缺点以及在微服务中的实现

文章目录 前言一、XA 模式1.1 XA 模式原理1.2 XA 模式的优缺点及应用场景1.3 Seata XA 模式在微服务中的实现 二、AT 模式2.1 Seata AT 模式原理2.2 AT 模式的脏写问题和写隔离3.3 AT 模式的优缺点3.4 Seata AT 模式在微服务中的实现 三、TCC 模式3.1 TCC 模式原理3.2 Seata 的…

洛谷 P1020 [NOIP1999 普及组] 导弹拦截【一题掌握三种方法:动态规划+贪心+二分】最长上升子序列LIS解法详解

P1020 [NOIP1999 普及组] 导弹拦截 前言题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题目分析注意事项 代码动态规划&#xff08;NOIP要求&#xff1a;时间复杂度O(n^2^)&#xff09;贪心二分&#xff08;O(nlgn)&#xff09; 后话额外测试用例样例输入 #1…

数据结构:Map和Set(2):相关OJ题目

目录 136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 771. 宝石与石头 - 力扣&#xff08;LeetCode&#xff09; 旧键盘 (20)__牛客网 (nowcoder.com) 138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 692. 前K个高频单词 - 力扣&#xff08…

“百人专家团”背书 袋鼠妈妈“双十一”蓄势待发

从万千商家的角度来看,“双十一”实际上就是一场没有硝烟的“战争”,只有用心做产品的品牌才能成为常胜将军,要想在双十一脱颖而出在同品类榜单上占据有利位置,品牌力和产品力二者缺一不可。而专注母婴护肤10年的袋鼠妈妈品牌便是如此,从品牌诞生以来,始终专注母婴用户需求,打造…

STM32MPU6050角度的读取(STM32驱动MPU6050)

注&#xff1a;文末附STM32驱动MPU6050代码工程链接&#xff0c;需要的读者请自取。 一、MPU6050介绍 MPU6050是一款集成了三轴陀螺仪和三轴加速度计的传感器芯片&#xff0c;由英国飞利浦半导体&#xff08;现为恩智浦半导体&#xff09;公司生产。它通过电子接口&#xff08…

面包屑实现

背景&#xff1a;面包屑根据菜单内容显示不同内容。首页永远存在&#xff0c;后面的活动管理及多级菜单的面包屑展示。 实现原理&#xff1a; 通过this.$route.matched获取所有匹配路由&#xff0c;将处理首页外的其他路由设置到一个数组中&#xff0c;再通过数组循环方式显示…

Linux/centos上如何配置管理Web服务器?

Linux/centos上如何配置管理Web服务器&#xff1f; 1 Web简单了解2 关于Apache3 如何安装Apache服务器&#xff1f;3.1 Apache服务安装3.2 httpd服务的基本操作 4 如何配置Apache服务器&#xff1f;4.1 关于httpd.conf配置4.2 常用指令 5 简单实例 1 Web简单了解 Web服务器称为…

一篇文章让你Docker从入门到精通

一篇文章让你Docker从入门到精通 Docker简介docker的3要素docker安装--centos7示例docker底层原理docker常用命令docker镜像原理数据共享--容器数据卷数据卷容器dockerfile解析Dockerfile实战一 使用dockerfile构建ubuntu镜像&#xff0c;并在里面安装vim及网络工具 一张图展示…

2023 年微服务后端开发的 11 个最佳工具

前言 微服务架构以将复杂的应用程序分解为易管理的服务而闻名&#xff0c;然而&#xff0c;管理微服务是一项具有挑战性的任务。为了确保开发工作流程的高效性&#xff0c;需要采用特定的工具。 在本文中&#xff0c;小编将为您介绍2023年最热的11款后端微服务开发工具&#…

什么是CE认证?蓝牙耳机出口欧盟CE认证如何办理?CE-RED认证办理

蓝牙耳机是一种基于蓝牙技术的一种小型设备&#xff0c;只需要把这种轻巧的设备藏在耳机边而不需要直接使用通讯设备&#xff08;手机、电脑等&#xff09;就可以实现自由通话。蓝牙耳机就是将蓝牙技术应用在免持耳机上&#xff0c;让使用者可以免除恼人电线的牵绊&#xff0c;…

软件测试/测试开发丨接口自动化测试学习笔记,整体结构响应断言

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27982 一、结构断言介绍 针对于“大响应数据”如何断言 针对主要且少量的业务断言其他字段不做数据正确性断言&#xff0c;只做类型与整体结构校验与前面…

【Ruoyi管理后台】用户登录强制修改密码

近期有个需求&#xff0c;就是需要调整Ruoyi管理后台&#xff1a;用户如果三个月(长时间)未修改过密码&#xff0c;需要在登录时强制修改密码&#xff0c;否则不能登录系统。 一、后端项目调整 从需求来看&#xff0c;我们需要在用户表增加一个字段&#xff0c;用于标记用户最…