制作和维系一个网站的费用,广西建设网站首页,免费申请163邮箱,淄博网站建设哪家便宜c primer plus 第15章友#xff0c;异常和其他#xff1a;友元类 提示#xff1a;这里可以添加系列文章的所有文章的目录#xff0c;目录需要自己手动添加 例如#xff1a;友元类 提示#xff1a;写完文章后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的…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.hbool 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.hint 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类的私有部分设置为公有的或者创建一个笨拙的、大型类来包含电视机和遥控器。这种解决方法无法反应这样的事实即同一个遥控器可用于多台电视机。