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 parts
    enum {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 off
    int volume;            // assumed to be digitized
    int maxchannel;        // maximum number of channels
    int channel;           // current channel setting
    int mode;              // broadcast or cable
    int 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;
    }
    else
        return false;
}
bool Tv::voldown()
{
    if (volume > MinVal)
    {
        volume--;
        return true;
    }
    else
        return false;
}

void Tv::chanup()
{
    if (channel < maxchannel)
        channel++;
    else
        channel = 1;
}

void Tv::chandown()
{
    if (channel > 1)
        channel--;
    else
        channel = 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.mfbz.cn/a/771282.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iPhone白苹果怎么修复?4个方法解决你的烦恼!

其实iPhone手机出现“白苹果”这事&#xff0c;如果是iPhone轻度用户&#xff0c;可能大家一辈子都不会遇到一次。但如果是iPhone重度用户、越狱爱好者、软件收集狂&#xff0c;可能就会遇到了。 白苹果&#xff0c;一般指iOS设备出现软、硬件故障&#xff0c;卡在一个类似于启…

6年铲屎官测评宠物空气净化器哪款好,热门养宠空气净化器排名

作为一名资深猫奴&#xff0c;发现很多铲屎官每到春秋换季就开始疯狂打喷嚏、突然开始全身过敏。其原因是猫毛一到换季就开始疯狂掉毛&#xff0c;相对于可见猫毛&#xff0c;漂浮在空气中的浮毛就是罪灰祸首。微小的浮毛在空气总容易被人体吸入体内&#xff0c;而浮毛上面附带…

音乐剪辑免费软件有哪些?7个音频剪辑技巧!

音乐剪辑免费软件有很多&#xff0c;但是适合自己或适合剪辑小白的却屈指可数。 音频剪辑软件千千万&#xff0c;如果是没有任何剪辑经验的小白用户&#xff0c;个人建议使用知名度较高的音频剪辑软件。不管是免费还是收费的音频剪辑软件&#xff0c;只要能够解决问题&#xf…

基于opencv的斜光测距及python实现

1.前言 最近做了一个基于opencv的斜光测距的小项目&#xff0c;东西不多&#xff0c;但是很有意思&#xff0c;值得拿出来学一学。项目里面需要比较精确的定位功能&#xff0c;将前人matlab代码移植到python上&#xff0c;并且做了一些优化&#xff0c;简化逻辑(毕竟我是专业的…

如何选择快手矩阵系统:打造高效短视频营销的指南

快手作为中国领先的短视频社交平台&#xff0c;为内容创作者和品牌提供了广阔的展示舞台。为了更高效地管理和扩展在快手上的影响力&#xff0c;快手矩阵系统成为了一个重要的工具。本文将指导您如何选择一个合适的快手矩阵系统&#xff0c;以优化您的内容管理和营销策略。 快…

Kotlin和Java的一些不同点

1.Kotlin 的变量是没有默认值的&#xff08;因此要求初始化&#xff09;&#xff0c;Java的成员变量是有默认值的 Java的成员变量&#xff1a; String name; // 默认值是 null int count; // 默认值是 0不过其实 Java 也只是成员变量有默认值&#xff0c;局部变量也是没有默…

中俄汽车产业链合作前景广阔,东方经济论坛助力双边合作与创新

随着中国汽车零部件企业的竞争力和创新能力不断增强&#xff0c;中国汽车及零部件行业在俄罗斯的市场份额和品牌影响力显著提升&#xff0c;中俄两国在汽车产业链上的合作展现出巨大的潜力和广阔的前景。2024年5月&#xff0c;俄罗斯乘用车新车销量达到12.8万辆&#xff0c;同比…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验15 网络故障导致的路由环路问题

一、实验目的 1.验证因网络故障而导致的静态路由的路由环路问题&#xff1b; 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实验内容 1.构建网络拓扑&#xff1b; 2.验证网络故障导致的…

LTSPICE仿真电路:(十九)磁珠的一些简单仿真

1.作用 简单来说就是用来滤波的&#xff0c;将高频信号转化为热量滤除掉&#xff0c;低频有用信号正常通过 2.参数 上图几个参数比较简单&#xff0c;就是字面上的意思&#xff0c;更重要的就是频率阻抗图 不同曲线代表不同型号的磁珠&#xff0c;实际上除了额定电流外&#…

Spring框架的学习SpringMVC(1)

1.什么是MVC (1)MVC其实就是软件架构的一种设计模式&#xff0c;它将软件的系统分为&#xff0c;&#xff08;视图&#xff0c;模型&#xff0c;控制器&#xff09;三个部分 1.1View(视图) 视图也就是&#xff0c;在浏览器显示的那一个部分&#xff0c;是后端数据的呈现 1.…

某DingTalk企典 - Token

⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识&#xff0c;欢迎私信共享学习心得。 如有侵权&#xff0c;联系博主删除。 请勿商用&#xff0c;否则后果自负。 网址 aHR0cHM6Ly9kaW5ndGFsay5jb20vcWlkaWFuLw 浅聊一下 没毛病&#xff0c;就这字段&#xff0c;有效期…

二叉树与堆相关的时间复杂度问题

目录 满二叉树与完全二叉树高度h和树中节点个数N的关系 向上调整算法&#xff1a; 介绍&#xff1a; 复杂度推导&#xff1a; 向下调整算法&#xff1a; 介绍&#xff1a; 复杂度推导&#xff1a; 向上调整建堆&#xff1a; 介绍&#xff1a; 复杂度推导&#xff1a;…

9.x86游戏实战-汇编指令mov

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

怎么找到DNS服务器的地址?

所有域都注册到域名名称服务器&#xff08;DNS&#xff09;点&#xff0c;以解析域名应指向的IP地址。此查找类似于在查找个人名称并查找其电话号码时的电话簿如何运行。如果DNS服务器设置错误或指向错误的名称服务器&#xff0c;则域可能无法加载相应的网页。 如何查找当前的…

【python基础】—calendar模块

文章目录 前言一、calendar模块方法1.firstweekday()2.setfirstweekday(firstweekday)3.isleap(year)4.leapdays(y1, y2)5.weekday(year, month, day)6.monthrange(year, month)7.weekheader(n)8.monthcalendar(year, month)9.prmonth(theyear, themonth, w0, l0)10.prcal(year…

堆结构、堆排序

堆 是完全二叉树&#xff0c;类似这种样式的 而这种有右子节点&#xff0c;没左子节点的就不是完全二叉树 分为大根堆和小根堆 大根堆是二叉树里每一颗子树的父节点都是这颗子树里最大的&#xff0c;即每一棵子树最大值是头节点的值 小根堆相反 把数组中从0开始的一段数人…

【等保2.0是什么意思?等保2.0的基本要求有哪些? 】

一、等保2.0是什么意思&#xff1f; 等保2.0又称“网络安全等级保护2.0”体系&#xff0c;它是国家的一项基本国策和基本制度。在1.0版本的基础上&#xff0c;等级保护标准以主动防御为重点&#xff0c;由被动防守转向安全可信&#xff0c;动态感知&#xff0c;以及事前、事中…

Stable Diffusion图像的脸部细节控制——采样器全解析

文章目录 艺术地掌控人物形象好易智算原因分析为什么在使用Stable Diffusion生成全身图像时&#xff0c;脸部细节往往不够精细&#xff1f; 解决策略 局部重绘采样器总结 艺术地掌控人物形象 在运用Stable Diffusion这一功能强大的AI绘图工具时&#xff0c;我们往往会发现自己…

开源的基于图像识别本地实名认证系统(本项目不借助任何api) v1.0

前言: 本项目主要是代替昂贵的实名认证服务api或者sdk&#xff0c;目前仍然存在很多缺点 一、具体介绍 1.组成: 人脸识别服务器分为两部分: (1)、http服务端 server.py共有四个函数: DrawFaceinIdCard:用户上传身份证图片后&#xff0c;服务端会对身份证进行抠人像和ocr处理…

澳蓝荣耀时刻,6款产品入选2024年第一批《福州市名优产品目录》

近日&#xff0c;福州市工业和信息化局公布2024年第一批《福州市名优产品目录》&#xff0c;澳蓝自主研发生产的直接蒸发冷却空调、直接蒸发冷却组合式空调机组、间接蒸发冷水机组、高效间接蒸发冷却空调机、热泵式热回收型溶液调湿新风机组、防火湿帘6款产品成功入选。 以上新…