c++ primer plus 第15章友,异常和其他:异常,15.3.3 异常机制

#c++ primer plus 第15章友,异常和其他:异常,15.3.3 异常机制
异常,15.3.3 异常机制

文章目录

  • 15.3.3 异常机制
    • 15.3.3 异常机制
    • 程序清单 15.9error3.cpp
    • 15.3.4 将对象用作异常类型
    • 程序清单15.10exc mean.h
    • 程序清单 15.11error4.cpp


15.3.3 异常机制

15.3.3 异常机制

下面介绍如何使用异常机制来处理错误。C++异常是对程序运行过程中发生的异常情况(例如被0除)的一种响应。异常提供了将控制权从程序的一个部分传递到另一部分的途径。对异常的处理有3个组成部分:

  • 引发异常;
  • 使用处理程序捕获异常;
  • 使用 try 块。
  • 程序在出现问题时将引发异常。例如,可以修改程序清单15.7中的hmean(),使之引发异常,而不是调用 abort()函数。throw语句实际上是跳转,即命令程序跳到另一条语句。throw 关键字表示引发异常,紧随其后的值(例如字符串或对象)指出了异常的特征。

程序使用异常处理程序(exceptionhandler)来捕获异常,异常处理程序位于要处理问题的程序中。catch关键字表示捕获异常。处理程序以关键字catch开头,随后是位于括号中的类型声明,它指出了异常处理程序要响应的异常类型:然后是一个用花括号括起的代码块,指出要采取的措施。catch 关键字和异常类型用作标签,指出当异常被引发时,程序应跳到这个位置执行。异常处理程序也被称为 catch块。
try 块标识其中特定的异常可能被激活的代码块,它后面跟一个或多个 catch 块。try 块是由关键字 try指示的,关键字 try 的后面是一个由花括号括起的代码块,表明需要注意这些代码引发的异常。要了解这3个元素是如何协同工作的,最简单的方法是看一个简短的例子,如程序清单15.9所示。

程序清单 15.9error3.cpp

// error3.cpp -- using an exception
#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 {                   // start of try blockz = hmean(x,y);}                       // end of try blockcatch (const char * s)  // start of exception handler{std::cout << s << std::endl;std::cout << "Enter a new pair of numbers: ";continue;}                       // end of handlerstd::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); 
}

程序说明
在程序清单 15.9中,try块与下面类似:

try {
z = hmean(x,y);
}
// start of try block
// end of try block

如果其中的某条语句导致异常被引发,则后面的 catch 块将对异常进行处理。如果程序在 try块的外面调用 hmean(),将无法处理异常。
引发异常的代码与下面类似:

if(a == -b)
throw "bad hmean()arguments:a=-b not allowed";

其中被引发的异常是字符串“bad hmean()arguments:a=-bnot allowed”。异常类型可以是字符串(就像这个例子中那样)或其他C++类型:通常为类类型,本章后面的示例将说明这一点。执行 throw 语句类似于执行返回语句,因为它也将终止函数的执行;但throw 不是将控制权返回给调用程序,而是导致程序沿函数调用序列后退,直到找到包含ty块的函数。在程序清单15.9中,该函数是调用函数。稍后将有一个沿函数调用序列后退多步的例子。另外,在这个例子中,throw 将程序控制权返回给 main()。程序将在 main()中寻找与引发的异常类型匹配的异常处理程序(位于try 块的后面)。处理程序(或catch块)与下面类似:

catch(char*s)//start of exception handler
std::cout <<s<<std::endl;
sdt::cout <<"Enter anew pair of numbers:";
continue;
//end of handler

catch 块点类似于函数定义,但并不是函数定义。关键字 catch 表明这是一个处理程序,而 chars则表明该处理程序与字符串异常匹配。s与函数参数定义极其类似,因为匹配的引发将被赋给s。另外,当异常与该处理程序匹配时,程序将执行括号中的代码。
执行完 try 块中的语句后,如果没有引发任何异常,则程序跳过tny块后面的 catch 块,直接执行处理程序后面的第一条语句。因此处理值3和6时,程序清单15.9中程序执行报告结果的输出语句。接下来看将 10和-10传递给 hmean()函数后发生的情况。If语句导致 hmean( )引发异常。这将终止
hmean()的执行。程序向后搜索时发现,hmean()函数是从 main()中的try块中调用的,因此程序查找与异常类型匹配的 catch 块。程序中唯一的一个 catch 块的参数为char
,因此它与引发异常匹配。程序将字符串“bad hmean( )arguments:a=-bnotallowed”赋给变量s,然后执行处理程序中的代码。处理程序首先打印 s–捕获的异常,然后打印要求用户输入新数据的指示,最后执行continue语句,命令程序跳过 while循环的剩余部分,跳到起始位置。continue使程序跳到循环的起始处,这表明处理程序语句是循环的一部分,而catch行是指引程序流程的标签(参见图15.2)。
在这里插入图片描述
您可能会问,如果函数引发了异常,而没有ty块或没有匹配的处理程序时,将会发生什么情况。在默认情况下下,程序最终将调用 abort()函数,但可以修改这种行为。稍后将讨论这个问题。

15.3.4 将对象用作异常类型

通常,引发异常的函数将传递一个对象。这样做的重要优点之一是,可以使用不同的异常类型来区分不同的函数在不同情况下引发的异常。另外,对象可以携带信息,程序员可以根据这些信息来确定引发异常的原因。同时,catch 块可以根据这些信息来决定采取什么样的措施。例如,下面是针对函数 hmean()引发的异常而提供的一种设计:

class bad_hmean
{
private :
double vl;
double v2;
public:bad hmean(int a=0,intb=0):v1(a)v2(b){}
void mesg();
}
inline void bad hmean::mesg()
std::cout << "hmean(" << vl << "," << v2 <<"):
<< "invalid arguments:a=-bn";
}

可以将一个 bad hmean 对象初始化为传递给函数hmean()的值,而方法 mesg()可用于报告问题(包括传递给函数 hmena()的值)。函数hmean()可以使用下面这样的代码:

if(a == -b)
throw bad hmean(a,b);

上述代码调用构造函数bad hmean(),以初始化对象,使其存储参数值。程序清单 15.10和 15.11添加了另一个异常类 bad_gmean 以及另一个名为 gmean()的函数,该函数引发bad gmean 异常。函数 gmean()计算两个数的几何平均值,即乘积的平方根。这个函数要求两个参数都不为负,如果参数为负,它将引发异常。程序清单15.10是一个头文件,其中包含异常类的定义:而程序清单 15.11是一个示例程序,它使用了该头文件。注意,try块的后面跟着两个 catch 块:

try
{
// start of try block
...
}// end of try block
//start of catch blockcatch(bad hmean &bg)
catch(bad gmean &hg)
{
//end of catch block
}

如果函数 hmean()引发 bad_hmean 异常,第一个 catch块将捕获该异常;如果 gmean()引发bad_gmean异常,异常将逃过第一个catch块,被第二个catch 块捕获。

程序清单15.10exc mean.h

// exc_mean.h  -- exception classes for hmean(), gmean()
#include <iostream>class bad_hmean
{
private:double v1;double v2;
public:bad_hmean(double a = 0, double b = 0) : v1(a), v2(b){}void mesg();
};inline void bad_hmean::mesg()
{   std::cout << "hmean(" << v1 << ", " << v2 <<"): "<< "invalid arguments: a = -b\n";
}class bad_gmean
{
public:double v1;double v2;bad_gmean(double a = 0, double b = 0) : v1(a), v2(b){}const char * mesg();
};inline const char * bad_gmean::mesg()
{  return "gmean() arguments should be >= 0\n";
}

程序清单 15.11error4.cpp

//error4.cpp ?using exception classes
#include <iostream>
#include <cmath> // or math.h, unix users may need -lm flag
#include "exc_mean.h"
// function prototypes
double hmean(double a, double b);
double gmean(double a, double b);
int main()
{using std::cout;using std::cin;using std::endl;double x, y, z;cout << "Enter two numbers: ";while (cin >> x >> y){try {                  // start of try blockz = hmean(x,y);cout << "Harmonic mean of " << x << " and " << y<< " is " << z << endl;cout << "Geometric mean of " << x << " and " << y<< " is " << gmean(x,y) << endl;cout << "Enter next set of numbers <q to quit>: ";}// end of try blockcatch (bad_hmean & bg)    // start of catch block{bg.mesg();cout << "Try again.\n";continue;}                  catch (bad_gmean & hg) {cout << hg.mesg();cout << "Values used: " << hg.v1 << ", " << hg.v2 << endl;cout << "Sorry, you don't get to play any more.\n";break;} // end of catch block}cout << "Bye!\n";// cin.get();// cin.get();return 0;
}double hmean(double a, double b)
{if (a == -b)throw bad_hmean(a,b);return 2.0 * a * b / (a + b);
}double gmean(double a, double b)
{if (a < 0 || b < 0)throw bad_gmean(a,b);return std::sqrt(a * b); 
}

下面是程序清单15.10和15.11组成的程序的运行情况,错误的 gmean()函数输入导致程序终止:

首先,bad_hmean 异常处理程序使用了一条 continue语句,而bad_gmean 异常处理程序使用了一条 break语句。因此,如果用户给函数hmean()提供的参数不正确,将导致程序跳过循环中余下的代码,进入下一次循环;而用户给函数 gmean()提供的参数不正确时将结束循环。这演示了程序如何确定引发的异常(根据异常类型)并据此采取相应的措施。
其次,异常类 bad_gmean 和 bad hmean 使用的技术不同,具体地说,bad gmean 使用的是公有数据和一个公有方法,该方法返回一个C-风格字符串。

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

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

相关文章

【STM32标准库】DMA双缓冲模式

1.双缓冲模式简介 设置DMA_SxCR寄存器的DBM位为1可启动双缓冲传输模式&#xff0c;并自动激活循环模式&#xff0c;所以设置普通模式或者循环模式都可以。 双缓冲不应用与存储器到存储器的传输。可以应用在从存储器到外设或者外设到存储器。 双缓冲模式下&#xff0c; 两个存…

IC认证介绍

IC认证是什么&#xff1f; IC是加拿大工业部Industry Canada的简称&#xff0c;作为政府机构&#xff0c;负责电子电器产品进入加拿大市场的认证事务。与美国的FCC相似&#xff0c;IC目前只在电磁干扰上做限制。一般规定&#xff1a;仅限制EMI&#xff0c;认证方式也与FCC相同…

领略超越王勃的AI颂扬艺术:一睹其惊艳夸赞风采

今日&#xff0c;咱也用国产AI技术&#xff0c;文心一言3.5的文字生成与可灵的图像创作&#xff0c;自动生成一篇文章&#xff0c;提示语文章末下载。 【玄武剑颂星际墨侠】 苍穹为布&#xff0c;星辰织锦&#xff0c;世间万象&#xff0c;皆入我玄武剑公众号之浩瀚画卷。此号…

Python入门 函数传递

目录 函数的多返回值 函数的多种传参形式 位置参数 关键字参数 缺省参数 不定长参数 位置传递 关键字传递 函数作为参数传递 lambda匿名函数 函数定义中 匿名函数的语法 函数的多返回值 按照返回值的顺序&#xff0c;与对应顺序的多个变量接受即可 变量之间用逗号…

SPI协议——对外部SPI操作(跨页读写)

关于W25Q32JVSSIQ的详细内容在之前的两篇文章中已经详细介绍&#xff0c;本文不做太多赘述&#xff0c;如果对芯片的了解有缺失的话&#xff0c;可以参考&#xff1a; SPI协议——对外部SPI Flash操作-CSDN博客 SPI协议——读取外部SPI Flash ID_spi flash 读取id-CSDN博客 目录…

【SpringCloud应用框架】Nacos集群配置

第八章 Spring Cloud Alibaba Nacos之集群配置 文章目录 一、Linux版NacosMySql生产环境配置具体配置&#xff1a; 二、Nacos集群配置更改Nacos启动命令配置原理具体配置测试启动总结 一、Linux版NacosMySql生产环境配置 上一篇博客中已经了解了Nacos生产环境下需要搭建集群配…

XDMA原理学习(1)——DMA技术详解

目录 一、什么是DMA&#xff1f;为什么需要DMA&#xff1f; 二、DMA分类 2.1 Block DMA 2.2 Scatter-Gather DMA 2.3 Ring buffer DMA 三、实际案例 3.1 STM32微处理器 3.1.1 Block DMA 3.1.2 Scatter-Gather DMA 3.1.3 使用场景举例&#xff1a; 3.1.4 配置与实现 …

3GPP R18 Multi-USIM 是怎么回事?(三)

这篇内容相对来说都是一些死规定,比较枯燥。主要是与MUSIM feature相关的mobility and periodic registration和service request触发过程的一些规定,两部分的内容是有部分重叠的,为保证完整性,重复部分也从24.501中摘了出来。 24.501 4.25 网络和MUSIM UE可以支持MUSIM fe…

idea控制台乱码问题解决教程

注&#xff1a;按顺序来操作&#xff0c;完成后要重启软件 方案一&#xff1a;修改Tomcat的编码设置 在Tomcat的VM options中添加了-Dfile.encodingUTF-8 方案二&#xff1a;修改IDEA的编码设置 File->Settings->Editor->File Encodings 将Global Encoding、Proj…

STM32-外部中断浅析

本篇解释了STM32中断原理 MCU为什么需要中断 中断&#xff0c;是嵌入式系统中很重要的一个功能&#xff0c;在系统运行过程中&#xff0c;当出现需要立刻处理的情况时&#xff0c;暂停当前任务&#xff0c;转而处理紧急任务&#xff0c;处理完毕后&#xff0c;恢复之前的任务…

深度学习之正则化

目标 我们学习正则化之前应该先了解我们为什么要用正则化 。正则化解决了什么问题 。我们讲正则化之前 &#xff0c;先了解一个概念–》过拟合 过拟合 数据增强 L1和L2正则化 Dropout 注意&#xff1a;Dropout是不适合用在卷积神经网络的 提前终止 一般的做法是&#xff1a;记…

B端工作台如何设计?指导思想+布局建议+大厂案例全给你

一、B端工作台设计的指导思想 要做好B端工作台设计&#xff0c;以下是一些建议和策略&#xff1a; 1. 用户研究&#xff1a;深入了解目标用户的需求、行为和工作流程。通过用户研究方法&#xff0c;如用户访谈、观察和调研&#xff0c;收集用户反馈和意见&#xff0c;了解他们…

【计算机组成原理】计算机系统概述(上)

&#xff08;一&#xff09;计算机系统简介 计算机系统有“硬件”和“软件”两大部分组成。 1&#xff09;所谓“硬件”即指见计算机的实体部分&#xff0c;它由看得见摸得着的各种电子元器件、各类光、电、机设备的事物组成&#xff0c;如主机、外设等等。 2&#xff09;所谓…

以SGET协会OSM标准首创有662引脚的OSM模组——凌华智能引领嵌入式运算市场

在可焊接的45 x 45mm尺寸上提升功率 开启嵌入式运算发展的新时代 摘要&#xff1a; 1.开放式标准模块(OSM™)&#xff0c;最大尺寸仅45 x 45mm&#xff0c;采用零开销的模块化系统简化生产&#xff0c;并提供662个引脚以增强小型化和物联网应用。 2.凌华智能提供基于NXP i.M…

快速掌握AI的最佳途径实践

科技时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为许多人希望掌握的重要技能。对于普通人来说&#xff0c;如何快速有效地学习AI仍然是一个挑战。本文将详细介绍几种快速掌握AI的途径&#xff0c;并提供具体的操作步骤和资源建议。 前言 AI的普及和应用已经深…

独立站爆款产品的选品思路及底层逻辑拆解

在这个竞争激烈的跨境电商市场&#xff0c;有一件事情比网站设计、营销策略、物流服务都更重要。那就是选品。跨境独立站选品是独立站成功的第一步&#xff0c;如果选错了产品&#xff0c;那么所有努力都可能白费。可能会面临库存积压、利润低迷、客户流失等问题。但是如果选对…

HackTheBox--BoardLight

BoardLight 测试过程 1 信息收集 NMAP端口扫描 端口扫描开放 22、80 端口 80端口测试 # 添加 boardLight.htb 到hosts文件 echo "10.10.11.11 boardLight.htb" | sudo tee -a /etc/hosts检查网页源代码&#xff0c;发现 board.htb # 添加 board.htb 到 hosts 文…

星网安全产品线成立 引领卫星互联网解决方案创新

2024年6月12日&#xff0c;盛邦安全&#xff08;688651&#xff09;成立星网安全产品线&#xff0c;这是公司宣布全面进入以场景化安全、网络空间地图和卫星互联网安全三大核心能力驱动的战略2.0时代业务落地的重要举措。 卫星互联网技术的快速发展&#xff0c;正将其塑造为全球…

Camera Raw:裁剪

Camera Raw 的裁剪 Crop面板提供了裁剪、旋转、翻转、拉直照片等功能&#xff0c;通过它们可以更精确地调整照片的视角和范围&#xff0c;以达到最佳二次构图的视觉效果。 快捷键&#xff1a;C ◆ ◆ ◆ 使用方法与技巧 1、使用预设 选择多种裁剪预设&#xff08;如 1:1、16:…

【安全设备】下一代防火墙

一、什么是防火墙 防火墙是一个网络安全产品&#xff0c;它是由软件和硬件设备组合而成&#xff0c;在内网和外网之间、专用网与公共网之间的一种保护屏障。在计算机网络的内网和外网之间构建一道相对隔离的保护屏障&#xff0c;以达到保护资料的目的。它是一种隔离技术&#…