C++ primer Plus 第十五章 友元、异常和其他

C++ Primer Plus(第六版)编程练习答案 第15章 友元、异常和其他 本章所有编程练习的工程源码可在此处下载(点击此链接下载),供大家参考交流!   1. 对Tv和Remote类做如下修改: a. 让它们互为友元; b. 在Remote类中添加一个状态变量成员,该成员描述遥控器是处于常规模式还是互动模式; c. 在Remote中添加一个显示模式的方法; d. 在Tv类中添加一个对Remote中新成员进行切换的方法,该方法应仅当TV处于打开状态时才能运行。... 阅读详情

15.1友元

类并非只有友元函数,还可以有友元类,友元类的所有方法都可以访问原始类的私有成员和保护成员。

下面我们通过一个例子来讲解一下友元类

定义TV类和Rmote类,分别作为电视机和遥控器的类

由于遥控器可以控制电视机,即遥控器可以访问电视机的成员,所以要将Rmote类声明为TV的友元类,但是如果只是将Rmote类的一个成员函数声明为友元函数,则需要知道Rmote类的声明,所以TV类应该在Rmote类后声明,但是在Rmote类的声明中,有些成员函数会引用TV类的对象,这时候需要在Rmote类前对TV类进行名称声明(即声明TV 是一个类),这种做法叫做前向引用声明。

#include<iostream>
using namespace std;
class Tv;
class Remote
{
    int mode;
public:
    enum State{off,on};
    void onoff(Tv &t);
};
class Tv
{
    int state;
public:
    friend void Remote::onoff(Tv &t);//将Remote的onoff函数声明为Tv的友元函数
    enum State{off,on};
    void onoff(){state = (state == on)?off:on;}
};

如果我们希望电视机接受遥控器指令后,会返回信息给遥控器,遥控器会发出嗡嗡声作为回应。

这时候可以将Tv和Rmote类互为友元类,但是要注意如果Tv类声明在前的话,对于Tv类中使用Rmote类对象的方法的定义,需要在Remote声明之后。

例如

这种使用内联函数的,即使用了Tv类的具体成员的内联函数,要使用inline关键字 在Tv类声明的后面定义。

 

15.3异常

 

15.3.1调用abort()

abort函数位于cstdlib头文件里,其典型实现是向标准错误流即cerr发送程序异常终止,然后终止程序。

也可以使用exit(),该函数会刷新文件缓冲区,但不显示消息。

如

#include<iostream>
#include<cstdlib>
using namespace std;
double heam(double a,double b);
void fun()
{
    double a,b;
    cin>>a>>b;
    double result = heam(a,b);//除运算
    cout<<result<<endl;
}
double heam(double a,double b)
{
    if(b==0)
    {
        cout<<"error"<<endl;
        abort();//也可以用exit(0)
    }
}
int main()
{
    fun();
}

如果b==0的话说明发生错误了,执行abort,会直接结束程序,而不是结束函数。

 

15.3.3异常机制

对异常的处理分为三个部分:

引发异常;

使用处理程序捕获异常;

使用try块;

 

try块标识其中特定的异常可能被激活的代码块,它后面跟一个或多个catch块

catch关键字表示捕获异常,处理程序以关键字catch开头,随后是位于括号中的类型声明,它指出了异常处理程序要响应的异常类型,然后是一个花括号括起来的代码块,指出要采取的措施。

throw 类似于return,它将终止函数的执行,并返回相应的值;但throw不是将控制权返回给调用程序,而是导致程序函数调用序列回退,一直到包含try块的那个函数,并将返回值与catch的异常类型比较,以执行特定的代码块,这个过程叫做栈解退。

例如:

#include<iostream>
#include<cstdlib>
using namespace std;
double heam(double a,double b)
{
    if(b==0)
    {
        throw "Error!";
    }
}
void fun()
{
    double a,b,result;
    cin>>a>>b;
    try
    {
        result = heam(a,b);//除运算
    }
    catch(const char *s)//会将throw返回的那个字符串与s的类型匹配,所以执行这异常处理的代码块
    {
        cout<<s<<endl;
        abort();
    }
    cout<<result<<endl;
}

int main()
{
    fun();
}

15.3.4将对象用作异常的类型

 

我们可以手动定义异常的类,为不同异常创建不同的类,以便于在多个catch里找到应执行的代码块。

15.3.5异常规范

如

double harm(double a) throw(bad_thing);
double marm(double) throw();

其中throw()部分就是异常规范,它可能是出现在函数原型和函数定义中,可能包含类型列表。

这项功能不推荐使用,仅了解即可。

 

15.3.6栈解退

 

1.在try的语句块内声明的变量在外部是不可以访问的,即使是在catch子句内也不可以访问。 
 
2.栈解退(寻找异常处理(exception handling)代码)

栈解退会沿着嵌套函数的调用链不断查找,知道找到了已抛出的异常匹配的catch子句。如果在最后还是没有找到对应的catch子句的话,则退出主函数后查找过程终止,程序调用标准函数库的terminate()函数,终止该程序的执行

1.当一个exception被抛出的时候,控制权会从函数调用中释放出来,并需找一个可以处理的catch子句
2.对于一个抛出异常的try区段,程序会先检查与该try区段关联的catch子句,如果找到了匹配的catch子句,就使用这个catch子句处理这个异常。
3.没有找到匹配的catch子句,如果这个try区段嵌套在其他try区段中,则继续检查与外层try匹配的catch子句。如果仍然没有找到匹配的catch子句,则退出当前这个主调函数,并在调用了刚刚退出的这个函数的其他函数中寻找。

3. catch子句的查找: 
 
1.catch子句是按照出现的顺序进行匹配的(以例2来说,异常先会匹配catch(exception e)子句,然后在匹配 catch (Exception e)子句,一步一步的栈展开)。在寻找catch子句的过程中,抛出的异常可以进行类型转换,但是比较严格:
2.允许从非常量转换到常量的类型转换(权限缩小)
3.允许从派生类到基类的转换。
4.允许数组被转换成为指向数组(元素)类型的指针,函数被转换成指向该函数类型的指针(降级问题)
5.标准算术类型的转换(比如:把bool型和char型转换成int型)和类类型转换(使用类的类型转换运算符和转换构造函数)。


15.5.7其他异常特性

1.如果抛出的异常一直没有函数捕获(catch),则会一直上传到c++运行系统那里,导致整个程序的终止

2.一般在异常抛出后资源可以正常被释放,但注意如果在类的构造函数中抛出异常,系统是不会调用它的析构函数的,处理方法是:如果在构造函数中要抛出异常,则在抛出前要记得删除申请的资源。

3.异常处理仅仅通过类型而不是通过值来匹配的,所以catch块的参数可以没有参数名称,只需要参数类型。

4.函数原型中的异常说明要与实现中的异常说明一致,否则容易引起异常冲突。

5.应该在throw语句后写上异常对象时,throw先通过Copy构造函数构造一个新对象,再把该新对象传递给 catch.  

注:那么当异常抛出后新对象如何释放?

异常处理机制保证:异常抛出的新对象并非创建在函数栈上,而是创建在专用的异常栈上,因此它才可以跨接多个函数而传递到上层,否则在栈清空的过程中就会被销毁。所有从try到throw语句之间构造起来的对象的析构函数将被自动调用。但如果一直上溯到main函数后还没有找到匹配的catch块,那么系统调用terminate()终止整个程序,这种情况下不能保证所有局部对象会被正确地销毁。
6.catch块的参数推荐采用地址传递而不是值传递,不仅可以提高效率,还可以利用对象的多态性。另外,派生类的异常扑获要放到父类异常扑获的前面,否则,派生类的异常无法被扑获。

7.编写异常说明时,要确保派生类成员函数的异常说明和基类成员函数的异常说明一致,即派生类改写的虚函数的异常说明至少要和对应的基类虚函数的异常说明相同,甚至更加严格,更特殊。
 

15.4RTTI以及类型转换运算符

RTTI是运行阶段类型识别的简称。

RTTI包含dynamic_cast、typeid和type_info

类型转换运算符包含 dynamic_case const_cast static_cast  reinterpret_cast.

1.dynamic_cast运算符:最常用的RTTI组件

Superb *pm=dynamic_cast<Superb *>(pg);

若pg的类型能够被安全地转化为Superb*,如果可以,返回对象的地址,否则,返回一个空指针。

dynamic_cast<Type*>(pt);正确,返回Type*,否则,返回0。

2.typeid使得能够确定两个对象是否为同种类型,可接受两个参数:类名和结果为对象的表达式。返回值为type_info对象的引用。

typeid(Magnificent)==typeid(*pg);

pg为空指针会抛出异常bad_typeid。type_info含有name()函数,返回类名。

3.const_cast<type-name> (expression) 转变为const或者volatile类型,typename与expression类型相同

4.static_cast<type-name>(expression) type-name转化为expression或者expression转化为type-name时均可使用。枚举/整型互转,double/int互转。

5.reinterpret_cast<type-name>(expression)

函数指针不可转化为数据指针,指针不能转为整型或者浮点

C++ Primer Plus学习(十四)——友元、异常和其他 友元、异常和其他友元友元类友元成员函数其他友元关系共同的友元嵌套类异常RTTI类型转换运算符 友元 友元类 友元成员函数 其他友元关系 共同的友元 嵌套类 异常 RTTI 类型转换运算符 阅读详情

相关推荐

北斗B1频点信号捕获实战:如何应对NH码跳变带来的挑战?

本文深入探讨了北斗B1频点信号捕获中NH码跳变带来的核心挑战。针对NH码以1kHz速率调制导致的相干积分中断和相关峰畸变问题,文章提出并详细解析了一种基于伪码与多普勒频率分离技术的优化捕获方案。该方案通过差分处理消除NH跳变影响,并利用匹配滤波器与FFT分别进行码相位和多普勒频率的快速估计,有效提升了弱信号环境下的捕获灵敏度和稳定性,为北斗接收机设计提供了实用的工程参考。

joy55的博客 534

C++ Primer Plus学习笔记-第十五章:友元,异常和其它

第十五章:友元,异常和其它 文章目录第十五章:友元,异常和其它1.友元2.嵌套类3.异常4.RTTI5.类型转换运算符以上为本章所有内容! 前言:本章有三个主要内容,分别是友元,异常和其它;本章除了进一步深入剖析友元的使用(不仅仅是友元函数,还包括友元类),还会提供关于异常的处理方式(这对大型程序的稳定性十分重要),另外还会额外讨论一些其它知识; 1.友元 友元函数可用于扩展类的接口,而友元类的所有方法则都可以使用被友元类的数据成员,包括公有私有保护等所有成员; 在一个类中将另一个类声明为友元,只需在一个类

m0_55639846的博客 575

npu-smi info 华为昇腾NPU 状态监控工具解读

用于查询所有设备的基本信息。

Lixora's DB Home 2486

《C++ primer plus》第15章:友元、异常和其他(1)

友元类

weixin_40064300的博客 964

Python手记-9:Python LXML库XPath的爬取晋江书目

1. lxml库 lxml是功能最丰富且易于使用的库,用于处理Python语言中的XML和HTML,还可实现WEB爬取,官文参考:https://lxml.de/,完整的PDF文档下载链接https://lxml.de/lxmldoc-4.5.0.pdf,但是阅读起来……em……怪自己不够聪明的样子。 Linux下安装lxml库:[root@chengyu ~]# pip3 instal...

成屿的专栏 4万+

阿里开源最强数字人工具 EchoMimicV2,本地部署(一)

EchoMimicV2是阿里推出的半身人体AI数字人项目,基于参考图片、音频剪辑和手部姿势序列生成高质量动画视频,确保音频内容与半身动作的一致性。现在本地部署,安装体验一下。

缘分天空的专栏 4614

C++ Primer Plus:第十五章 - 友元、异常和其他

0、本章内容: 友元类。 友元类方法。 嵌套类。 引发异常、try块和catch块。 异常类。 运行阶段类型识别(RTTI)。 dynamic_cast和typeid。 static_cast、const_cast和reiterpret_cast。 1、友元: 访问原始类私有成员和保护成员。 1.1 友元类 友元类声明位置无关紧要。 1.2 友元成员函数 注意声明和定义的顺序,合理使用前向...

qq_30534935的博客 292

【WRF教程第3.5期】预处理系统 WPS 详解:以4.5版本为例

预处理系统 WPS 详解:以4.5版本为例

WW、forever的博客 1422

C++PrimerPlus 第十五章 友元、异常和其他

1、如果将类B定义为类A的友元类,则在类A的声明中,添加语句friend class B;即可,这样一来,B就可以访问A中的私有成员和保护成员。 2、可以仅让特定的类成员成为另一个类的友元,而不必让整个类成为友元,但这样做稍微有点麻烦,必须小心排列各种声明和定义的顺序。 3、在C++中,可以把使用类声明放在另一个类中,在另一类中声明的类被称为嵌套类。 对类进行嵌套与包含并不相同,包含意味着将类...

一个小孩 328

157、飞控中的鲁棒自适应控制

本文总结了飞控系统中鲁棒自适应控制的实践经验。作者通过炸机案例引出传统PID控制的局限性,分析了鲁棒性与自适应性的本质矛盾,提出"用鲁棒性兜底,用自适应性提性能"的设计原则。重点介绍了模型参考自适应控制(MRAC)的实现方法,包括参考模型设计、自适应律调参技巧(建议初始增益设为0.01)、直接/间接自适应的应用场景差异,以及防止参数漂移的鲁棒修正方法。文章还分享了实际调试中的三大关键问题(初始值设定、激励条件、执行器饱和)及解决方案,并推荐了"鲁棒PID+自适应前馈"的混合架构。最后强调调试顺序应为先保证鲁

2401_88858637的博客 27

详解AUTOSAR:AUTOSAR架构中的配置文件(拓展篇—7)

查看AUTOSAR代码包时会发现一些这样格式的文件:xxx_PBcfg.c、xxx_Lcfg.c和xxx_Cfg.h,本篇博文讲一讲这几个配置文件的作用和特点。

不脱发的程序猿 2146

C++ primer plus 第15章 友元、异常和其他

1.嵌套类 嵌套类:将一个类的声明放在另一个类中,它通过提供新的类型类作用域来避免名称混乱。包含类的成员函数可以创建和使用被嵌套类的对象;而仅当声明位于公有部分,才能在包含类的外面使用嵌套类,而且必须使用作用域解析运算符。 对类进行嵌套与包含并不同,包含意味着将类对象作为另一个类的成员,而对类进行嵌套不创建类成员,而是定义了一种类型,该类型仅在包含嵌套类声明的类中有效。 2.异常 (1)异...

CHY1156957638的博客 444

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

c++ primer plus 第十五章笔记 友元,异常和其他

我们知道函数的调用是一个压栈的过程,此时函数c抛出异常后,将会直接结束函数c运行,退回到上一个函数的调用,即出栈,到函数b,在函数b中寻找能够处理该异常类型的catch异常处理函数,找不到直接退栈不会执行该函数的内容,再往前找,直到找到能够处理该异常类型的catch异常处理函数为止,如果退到最后main函数都没有能处理这个异常类型的catch异常处理函数,则结束程序运行,这个就是栈解退,即异常抛出后就会往回倒,找到能满足条件的函数,找不到就程序运行结束。什么是循环引用和循环依赖?

m0_51711089的博客 905

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C++ Primer Plus第六版第十五章友元、异常和其他编程练习答案

1. main #include "TV.h" int main() { using std::cout; Tv s42; Remote grey; cout << "Initial settings for 42\" TV:\n"; s42.settings(); grey.show_r_mode(); s42.change_r_mode(grey); s42.on...

qq_44800780的博客 357

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

《C++ Primer Plus(第六版)》(31)(第十五章 友元、异常和其他 笔记)

友元类,友元类函数,嵌套类,异常,运行时类型识别,type_id,type_info,各种转换 1.友元类,就在类中声明个friend class className;就行了。 这个是对所有成员有效的。 class A { public: A(int a){ _a = a; } friend class B; private: int _a; }; class B { public: int get(A a){ return a.

肥宝的实验室 2809

《C++ Primer Plus》第十五章——友元,异常和其他(笔记)

通常,如果指向对象(*pt)的类型为Type或者是从Type直接或间接派生而来的类型,则表达式。将指针pt转换为Type类型的指针;否则,结果为0,即空指针(主要的。使用友元类方法(例在Tv中使用Remote的友元类方法)时,应用。的引用,确定两个对象是否为同种类型(重载了==和!如果一个函数需访问两个类的私有数据,则需要将其设置为。:和catch()配套使用。中异常,并跳转到该位置执行。是确保安全的调用虚函数)

2403_86782268的博客 337

C++Primer Plus笔记——第十五章 友元、异常和其他总结及程序清单

目录 本章小结 程序清单 友元类 15.1 tv.h                   15.2 tv.cpp                   15.3 use_tv.cpp            15.4 tvfm.h 嵌套类  15.5 queuetp.h         15.6 nested.cpp 异常 15.7 error1.cpp          15.8 e...

YukinoAI的博客 1003

《C++ Primer Plus(第六版)》(32)(第十五章 友元、异常和其他 复习题答案)

15.7 复习题 1.下面建立友元的尝试有什么错误? a. class snap { friend clasp; ... }; class clasp{ ... };b. class cuff { public: void snip(muff&){..} ... }; class muff { friend void cuff::snip

肥宝的实验室 3045

《C++ Primer Plus(第六版)》(33)(第十五章 友元、异常和其他 编程题答案)

总结: 貌似越到后面,就经常出现了排版混乱的情况,不知道是原版的问题还是翻译本的问题。 程序例子也越来越抽象了,而且是说明的东西居多。 其实初学者,甚至学得好深入的人,接触的可能还是很少。 很多细节,只有在非常底层或者特定的应用中才会使用到。 或者,用到的时候,百度一下就可以了。 15.8 编程练习 1.对Tv和Remote类做如下修改: a.让他们互为友元; b.在Remote类中添加一个状态变量成员,该成员描述遥控器是川渝常规模式还是互动模式; c.在Remote中添加一个显示模式的方法; d.在Tv

肥宝的实验室 3088

C++Primer Plus笔记——第十五章 友元、异常和其他课后编程练习答案

课后编程练习答案 习题1                习题2               习题3             习题4 习题1 //tv.h #ifndef TV_H_ #define TV_H_ #include &lt;iostream&gt; using namespace std; class Tv { friend class Remote; public: ...

YukinoAI的博客 444

C++ primer Plus(第六版)第十五章 友元、异常和其他 章节编程练习答案

1.对Tv和Remote类做如下修改: a. 让它们互为友元; b. 在Remote类中添加一个状态变量成员,该成员描述遥控器是处于常规模式还是互动模式; c. 在Remote中添加一个显示模式的方法; d. 在Tv类中添加一个对Remote中新成员进行切换的方法,该方法应仅当TV处于打开状态时才能运行。 编写一个小程序来测试这些新特性。 完成如下: ...

是鲤鱼啊 412

C++ Primer Plus 第六版 第十五章 复习题

假设函数 f1()调用函数 f2()。f2()中的返回语句导致程序执行在函数 f1()中调用函数f2()后面的一条语句。找到这样的ty语句块后,将执行下一个匹配的 catch 语句块,而不是函数调用后的语句。对于示例#2,仅当指向 Superb 对象时,if条件才为true,如果指向的是从Superb派生出来的对象,则if条件不为true。为使类A拥有一个本身为类B的成员函数的友元,B的声明必须位于A的声明之前。同样,如果B拥有一个本身是A的成员函数的友元,则A的这个声明必须位于B的声明之前。

geesehoward20000的博客 538

《C++ Primer Plus(第六版)》(33)(第十五章 友元、异常和其他 编程题答案)...

15.8 编程练习 1.对Tv和Remote类做如下修改: a.让他们互为友元; b.在Remote类中添加一个状态变量成员,该成员描述遥控器是川渝常规模式还是互动模式; c.在Remote中添加一个显示模式的方法; d.在Tv类中添加一个队Remote中新成员进行切换的方法,该方法应仅当TV处于打开状态才能使用。 编写一个小程序来测试这些新特性。 Test.h // ...

weixin_30776545的博客 257

《C++ Primer Plus》读书笔记 第15章 友元、异常和其他

第15章 友元、异常和其他 1.友元类 可以将一个类作为另一个类的友元。友元类的所有方法都可以访问原始类的私有成员和保护成员。 通过在类中使用下面的语句来声明友元类: friend class class_name; 友元声明可以位于公有、私有或保护部分,其所在的位置无关紧要。 假设现在要定义一个Tv类和Remote类,前者表示电视机,后者表示遥控器。两者显然不符合is-a关系,电视机不是一个遥...

CraigMC的博客 843
上一篇: C++ primer Plus 第十四章 C++中的代码重用
下一篇: Mysql常用函数
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值