c++ primer plus 第15章友,异常和其他:友元类

c++ primer plus 第15章友,异常和其他:友元类

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:友元类


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • c++ primer plus 第15章友,异常和其他:友元类
  • 15.1 友元
    • 15.1.1 友元类
    • 程序清单 15.1 tv.h
    • 程序清单 15.2 tv.cpp
  • 总结


15.1 友元

本书前面的一些示例将友元函数用于类的扩展接口中,类并非只能拥有友元函数,也可以将类作为友元。在这种情况下,友元类的所有方法都可以访问原始类的私有成员和保护成员。另外,也可以做更严格的限制,只将特定的成员函数指定为另一个类的友元。哪些函数、成员函数或类为友元是由类定义的,而不能从外部强加友情。因此,尽管友元被授予从外部访问类的私有部分的权限,但它们并不与面向对象的编程思想相悖;相反,它们提高了公有接口的灵活性。

15.1.1 友元类

什么时候希望一个类成为另一个类的友元呢?我们来看一个例子。假定需要编写一个模拟电视机和遥控器的简单程序。决定定义一个Tv类和一个 Remote类,来分别表示电视机和遥控器。很明显,这两个类之间应当存在某种关系,但是什么样的关系呢?遥控器并非电视机,反之亦然,所以公有继承的is-a关系并不适用。遥控器也非电视机的一部分,反之亦然,因此包含或私有继承和保护继承的 has-a关系也不适用。事实上,遥控器可以改变电视机的状态,这表明应将 Romote 类作为Tv类的一个友元。首先定义Tv类。可以用一组状态成员(描述电视各个方面的变量)来表示电视机。下面是一些可能的状态:

  • 开/关;
  • 频道设置;
  • 音量设置;
  • 有线电视或天线调节模式;
  • TV 调谐或 A/V 输入。
  • 调节模式指的是,在美国,对于有线接收和 UHF 广播接收,14频道和14频道以上的频道间隔是不同的。输入选择包括TV(有线TV或广播TV)和 DVD。有些电视机可能提供更多的选择,如多种 DVD/蓝光输入,但对于这个示例的目的而言,这个清单足够了。

另外,电视机还有一些不是状态变量的参数。例如,可接收频道数随电视机而异,可以包括一个记录

这个值的成员。接下来,必须给类提供一些修改这些设置的方法。当前,很多电视机都将控件藏在面板后面,但大多数电视机还是可以在不使用遥控器的情况下进行换台等工作的,通常只能逐频道换台,而不能随意选台。同样,通常还有两个按钮,分别用来增加和降低音量。
遥控器的控制能力应与电视机内置的控制功能相同,它的很多方法都可通过使用Tv方法来实现。另外,遥控器通常都提供随意选择频道的功能,即可以直接从2频道换到20频道,并不用逐次切换频道。另很多遥控器都有多种工作模式,如用作电视控制器和 DVD遥控器。外,这些考虑因素表明,定义应类似于程序清单 15.1。定义中包括一些被定义为枚举的常数。下面的语句使 Remote 成为友元类:
friend class Remote;友元声明可以位于公有、私有或保护部分,其所在的位置无关紧要。由于Remote类提到了Tv类,所以编译器必须了解 Tv 类后,才能处理 Remote 类,为此,最简单的方法是首先定义 Tv类。也可以使用前向声明(forward delaration),这将稍后介绍。

程序清单 15.1 tv.h

// tv.h -- Tv and Remote classes
#ifndef TV_H_
#define TV_H_class Tv
{
public:friend class Remote;   // Remote can access Tv private partsenum {Off, On};enum {MinVal,MaxVal = 20};enum {Antenna, Cable};enum {TV, DVD};Tv(int s = Off, int mc = 125) : state(s), volume(5),maxchannel(mc), channel(2), mode(Cable), input(TV) {}void onoff() {state = (state == On)? Off : On;}bool ison() const {return state == On;}bool volup();bool voldown();void chanup();void chandown();void set_mode() {mode = (mode == Antenna)? Cable : Antenna;}void set_input() {input = (input == TV)? DVD : TV;}void settings() const; // display all settings
private:int state;             // on or offint volume;            // assumed to be digitizedint maxchannel;        // maximum number of channelsint channel;           // current channel settingint mode;              // broadcast or cableint input;             // TV or DVD
};class Remote
{
private:int mode;              // controls TV or DVD
public:Remote(int m = Tv::TV) : mode(m) {}bool volup(Tv & t) { return t.volup();}bool voldown(Tv & t) { return t.voldown();}void onoff(Tv & t) { t.onoff(); }void chanup(Tv & t) {t.chanup();}void chandown(Tv & t) {t.chandown();}void set_chan(Tv & t, int c) {t.channel = c;}void set_mode(Tv & t) {t.set_mode();}void set_input(Tv & t) {t.set_input();}
};
#endif

在程序清单15.1中,大多数类方法都被定义为内联的。除构造函数外,所有的Romote方法都将一个Tv 对象引用作为参数,这表明遥控器必须针对特定的电视机。程序清单15.2列出了其余的定义。音量设置函数将音量成员增减一个单位,除非声音到达最大或最小。频道选择函数使用循环方式,最低的频道设置为1,它位于最高的频道设置maxchannel之后。
很多方法都使用条件运算符在两种状态之间切换:

void onoff(){state=(state ==On)? ff :On;

如果两种状态值分别为tnue(1)和false(0),则可以结合使用将在附录E讨论的按位异或和赋值运算符(^=)来简化上述代码:

void onoff()state^=1;

程序清单 15.2 tv.cpp

// tv.cpp -- methods for the Tv class (Remote methods are inline)
#include <iostream>
#include "tv.h"bool Tv::volup()
{if (volume < MaxVal){volume++;return true;}elsereturn false;
}
bool Tv::voldown()
{if (volume > MinVal){volume--;return true;}elsereturn false;
}void Tv::chanup()
{if (channel < maxchannel)channel++;elsechannel = 1;
}void Tv::chandown()
{if (channel > 1)channel--;elsechannel = maxchannel;
}void Tv::settings() const
{using std::cout;using std::endl;cout << "TV is " << (state == Off? "Off" : "On") << endl;if (state == On){cout << "Volume setting = " << volume << endl;cout << "Channel setting = " << channel << endl;cout << "Mode = "<< (mode == Antenna? "antenna" : "cable") << endl;cout << "Input = "<< (input == TV? "TV" : "DVD") << endl;}
}

程序清单 15.3是一个简短的程序,可以测试一些特性。另外,可使用同一个遥控器控制两台不同的电视机。

//use_tv.cpp -- using the Tv and Remote classes
#include <iostream>
#include "tv.h"int main()
{using std::cout;Tv s42;cout << "Initial settings for 42\" TV:\n";s42.settings();s42.onoff();s42.chanup();cout << "\nAdjusted settings for 42\" TV:\n";s42.settings();Remote grey;grey.set_chan(s42, 10);grey.volup(s42);grey.volup(s42);cout << "\n42\" settings after using remote:\n";s42.settings();Tv s58(Tv::On);s58.set_mode();grey.set_chan(s58,28);cout << "\n58\" settings:\n";s58.settings();// std::cin.get();return 0; 
}

下面是程序清单15.1~程序清单15.3组成的程序的输出:
在这里插入图片描述

总结

这个练习的主要目的在于表明,类友元是一种自然用语,用于表示一些关系。如果不使用某些形式的友元关系,则必须将Tv类的私有部分设置为公有的,或者创建一个笨拙的、大型类来包含电视机和遥控器。这种解决方法无法反应这样的事实,即同一个遥控器可用于多台电视机。

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

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

相关文章

5个文章生成器免费版,自动写作文章更轻松

在这个信息如洪流般涌动的时代&#xff0c;写作所具有的重要性不言而喻。不管是学生需要完成的作业&#xff0c;还是职场人士得提交的报告&#xff0c;亦或是自媒体创作者必须输出的内容&#xff0c;都迫切要求我们具备一定的写作技能。然而&#xff0c;写作对很多人来说&#…

C++实现一个简单的Qt信号槽机制(1)

昨天写这个文章《深入探讨C的高级反射机制&#xff08;2&#xff09;&#xff1a;写个能用的反射库》的时候就在想&#xff0c;是不是也能在这套反射逻辑的基础上&#xff0c;实现一个类似Qt的信号槽机制&#xff1f; Qt信号槽机制简介 所谓的Qt的信号槽&#xff08;Signals …

隐私集合求交(PSI)原理深入浅出

隐私集合求交技术是多方安全计算领域的一个子问题&#xff0c;通常也被称为安全求交、隐私保护集合交集或者隐私交集技术等&#xff0c;其目的是允许持有各自数据集的双方或者多方&#xff0c;执行两方或者多方集合的交集计算&#xff0c;当PSI执行完成&#xff0c;一方或者两方…

@amap/amap-jsapi-loader实现高德地图嵌入React项目中,并且做到点击地图任意一处,获得它的经纬度

1.第一步要加入项目package.json中或者直接yarn install它都可以 想必大家应该都会 "amap/amap-jsapi-loader": "0.0.7"2.加入项目中 关于接口获取key的接口 大家改成自己对应的项目请求方法 import React, { PureComponent } from react; import { Input…

【前端--Vue】组件之间的多种通信方式,一文彻底搞懂组件通信!

本篇将重点讲解vue中的多种组件通信方式&#xff0c;包括【父传子】【子传父】【兄弟组件通信】【依赖注入】等等&#xff0c;并提供具体案例来让小伙伴们加深理解、彻底掌握&#xff01;喜欢的小伙伴们点赞收藏&#xff0c;持续关注哦~&#x1f495; &#x1f49f; 上一篇文章…

商务视频推广打造有吸引力的7个秘诀-华媒舍

商务视频推广是现代企业发展的重要工具&#xff0c;它能够帮助企业吸引更多的目标客户&#xff0c;提升品牌知名度&#xff0c;增加销售量。但是&#xff0c;如何打造一部有吸引力的商务视频推广呢&#xff1f;本文将为您介绍7个秘诀&#xff0c;帮助您在商务视频推广中取得成功…

性能测试-JMeter学习

1、给不同的访问口分配访问占比&#xff1b;例&#xff1a;登录30%&#xff0c;首页&#xff1a;20%&#xff0c;新增&#xff1a;50% 不同业务放到不同线程组里&#xff0c;实现不同业务的分配 使用吞吐量控制器&#xff0c;设置不同的占比 使用if控制器&#xff0c;设置不同…

单服务器推送还在用WebSocket?快试试更快的SSE

在传统的Web开发中&#xff0c;WebSocket常被用来实现实时双向通信。然而&#xff0c;对于只需要单向、从服务器到客户端的信息推送场景&#xff0c;Server-Sent Events (SSE) 提供了一种更轻量、更简单的解决方案。 SSE 和 WebSocket 特点的差异 SSE SSE 适用于服务器向客户…

恭喜!H医生一个月内荣获美国芝加哥大学访问学者邀请函

➡️【院校背景】 芝加哥大学&#xff08;英文&#xff1a;The University of Chicago&#xff0c;简称UChicago、“芝大”&#xff09;由石油大王约翰洛克菲勒于1890年创办&#xff0c;坐落于美国伊利诺伊州芝加哥市&#xff0c;一所私立研究型大学&#xff0c;属于全球大学校…

uboot run命令基本使用

run 命令可以用于运行环境变量的中定义的命令,run bootcmd 可以运行bootcmd中启动命令 作用:可以运行我们自定义的环境变量 include/command.h common/cli.c /*** board_run_command() - Fallback function to execute a command** When no command line features are enabled …

注意!高考志愿填报的两个优先原则,千万不要错过!

高考已经告一段落&#xff0c;接下来几天各省会陆续公布分数&#xff0c;然后就到了填报志愿的环节。高考志愿填报是一项影响深远的综合性决策&#xff0c;决定着每个考生的未来发展 。下面我谈谈我对高考填报的理解。我总结为&#xff1a;两个优先、三个因素。 一、两个优先 …

Prometheus 监控Kubelet的运行状态

kubelet通过/metrics暴露自身的指标数据。kubelet有两个端口都提供了这个url&#xff0c;一个是安全端口&#xff08;10250&#xff09;&#xff0c;一个是非安全端口&#xff08;10255&#xff0c;kubeadm安装的集群该端口是关闭的&#xff09;。安全端口使用https协议&#x…

初阶数据结构之二叉树

那么本篇文是初阶数据结构这个系列的最后一篇文章&#xff0c;那么闲话少叙&#xff0c;我们直接进入正题 在讲二叉树的一些之前知识点之前&#xff0c;我先给大家送个小礼物哈 手搓二叉树 typedef int BTDataType ; typedef struct BinaryTreeNode { BTDataType _data …

【病毒分析】假冒游戏陷阱:揭秘MBRlock勒索病毒及其修复方法

1.背景 在公众号文章中看到一篇名为《敲竹杠木马分析&#xff1a;虚假的植物大战僵尸杂交版》的文章&#xff0c;样本来源于某吧&#xff0c;对此我们对样本进行了提取分析。 文章链接&#xff1a;https://mp.weixin.qq.com/s/Up9u4DZtHnVNMiGBIHZzHw 2.恶意文件基础信息 文…

企业数据API平台:获取企业多维度信息

数据API平台是指提供一系列预先定义的接口、协议与工具&#xff0c;允许不同应用程序或系统之间进行数据交换和通信的平台。这些接口被称为数据API&#xff08;Data Application Programming Interface&#xff09;&#xff0c;是数据管理系统或应用程序提供的一组开放式接口。…

盘点几款国产AI高效神器!打工人赶紧码住

在这个AI技术飞速发展的时代&#xff0c;国产AI工具正成为提升工作效率的得力助手。作为AI工具测评博主&#xff0c;米兔有幸体验了多款国产AI工具&#xff0c;今天要向大家介绍几款超级好用的AI工具。这些工具不仅功能强大&#xff0c;而且操作简便&#xff0c;是职场人士不可…

45.使用hook点链表实现指定跳转

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 上一个内容&#xff1a;44.实现管理HOOK点的链表对象 以 44.实现管理HOOK点的链表对象 它的代码为基础进行修改 HOOKPOINT.cpp文科修改&#xff0c;修改了Fin…

秋招Java后端开发冲刺——并发篇2(JMM与锁机制)

本文对Java的内存管理模型、volatile关键字和锁机制进行详细阐述&#xff0c;包括synchronized关键字、Lock接口及其实现类ReentrantLock、AQS等的实现原理和常见方法。 一、JMM&#xff08;Java内存模型&#xff09; 1. 介绍 JMM定义了共享内存中多线程程序读写操作的行为规…

【电源专题】DC-DC电路设计为什么一般只考虑电感DCR而不考虑Q值呢?

什么是电感器(线圈)的Q值&#xff1f; Q值是表示电感器质量的参数。Q是Quality Factor&#xff08;质量系数&#xff09;的简称。线圈会顺利流过直流电流&#xff0c;但会对交流电流产生电阻。这称为感抗&#xff0c;交流频率越高则越大。 此外&#xff0c;绕组虽是导体…

MTK6769芯片性能参数_MT6769规格书_datasheet

联发科MT6769处理器采用了台积电12nm工艺。它具有8核CPU&#xff0c;采用2Cortex A75 2.0GHz 6Cortex A55 1.7GHz的构架。该处理器搭载了Mali-G52 MC2 GPU&#xff0c;运行速度高达820MHz&#xff0c;能够提供出色的图形处理性能。此外&#xff0c;MT6769还提供高达8GB的快速L…