01)什么时候使用友元类?
假如要编写一个电视机Tv类和一个遥控器Remote类,很显然,Tv类不是Remote类,Remote类也不是Tv类,即不存在is-a关系;
遥控器Remote类也不是电视Tv类的一部分,反之亦然,因此包含、私有继承、保护继承的has-a关系也不存在;
事实上,遥控器可以改变电视机的状态,这表明Remote类作为Tv类的一个友元。
02)下面的语句使Remote成为友元类:
friend class Remote;
友元声明可以位于Tv类的公有、私有或保护部分,其位置无关紧要;由于Remote类中使用了Tv类的一些方法,所以要先声明
Tv类,然后声明Remote类;也可以使用前向声明,以后将介绍;
03)友元类的所有方法都可以访问原始类的私有成员和保护成员,例如:
1 class A 2 { 3 friend class B; 4 5 private: int aa; 6 }; 7 8 class B 9 { 10 public: 11 void output() 12 { 13 cout << a.aa << endl; //直接访问A类中的私有数据aa 14 } 15 private: A a; //创建A类对象 16 17 } 18 19 20 ———————————————— 21 版权声明:本文为CSDN博主「风雪残存」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。 22 原文链接:https://blog.csdn.net/u012230798/article/details/86576169
参考博客:https://blog.csdn.net/u012230798/article/details/86576169
1 #ifndef TV_H_ 2 #define TV_H_ 3 4 class Tv 5 { 6 private: 7 int state; //on or off 8 int volume; //音量 9 int maxchannel; //频道的最大数 10 int channel; //选择的频道 11 int mode; //Antenna or able 12 int input; //TV or DVD 13 public: 14 friend class Remote; //声明Remote为Tv的一个友元类 15 enum {Off, On}; //电视机的开关 16 enum {MinVal,MaxVal}; //声音的最小和最大值 17 enum {Antenna, Cable}; //天线or电缆 18 enum {TV,DVD}; //TV模式orDVD模式 19 20 Tv(int s=Off,int mc=125) : state(s),volume(5),maxchannel(mc),channel(2),mode(Cable),input(TV) {}; 21 22 void onoff() {state = (state == On) ? Off:On;} //若state == On成立,则state=Off,否则state=On 23 bool ison() const {return state == On;} 24 bool volup(); //增大音量 25 bool voldown(); //减小音量 26 void chanup(); //频道数增大 27 void chandown(); //频道数减小 28 void set_mode() {mode = (mode == Antenna) ? Cable : Antenna;} 29 void set_input() {input = (input == DVD) ? TV:DVD;} 30 void settings() const; //diaplay all the settings 31 }; 32 33 /*Remote中的方法除了构造函数外,都调用了原始类Tv中的方法*/ 34 class Remote 35 { 36 private: 37 int mode; 38 public: 39 Remote(int m = Tv::TV) : mode(m) {} 40 bool volup(Tv & t) {return t.volup();} //直接调用Tv中的volup() 41 bool voldown(Tv & t) {return t.voldown();} 42 void onoff(Tv & t) {t.onoff();} 43 void chanup(Tv & t) {t.chanup();} 44 void chandown(Tv & t) {t.chandown();} 45 void set_chan(Tv & t,int c) {t.channel = c;} //友元类的所有方法(Tv & t也是)都可以访问原始类的私有成员和保护成员 46 void set_mode(Tv & t) {t.set_mode();} 47 void set_input(Tv & t) {t.set_input();} 48 }; 49 50 #endif
1 //tv.cpp 2 #include <iostream> 3 #include "tv.h" 4 5 /*Tv类中增大音量函数*/ 6 bool Tv::volup() 7 { 8 if(volum < MaxVal) 9 { 10 volume++; 11 return true; 12 } 13 else 14 return false; 15 } 16 17 /*Tv类中减小音量函数*/ 18 bool Tv::voldown() 19 { 20 if(volume > MinVal) 21 { 22 volume--; 23 return true; 24 } 25 else 26 return false; 27 } 28 29 /*Tv类中增大频道数函数*/ 30 void Tv::chanup() 31 { 32 if(channel < maxchannel) 33 channel++; 34 else 35 channel = 1; //增大到maxchannel后回到频道1 36 } 37 38 /*Tv类中减小频道数函数*/ 39 void Tv::chandown() 40 { 41 if(channel > 1) 42 channel--; 43 else 44 channel = maxchannel; //减小到频道1后换到频道最大值 45 } 46 47 /*diaplay all the settings*/ 48 void Tv::settings() const 49 { 50 using std::cout; 51 using std::endl; 52 53 cout << "Tv is " << (state = Off ? "Off" : "On") << endl; //此处则可以省略下面if的else语句 54 if(state == On) //On是在Tv中定义的一个枚举量 55 { 56 cout << "Volume setting = " << volume << endl; 57 cout << "Channel setting = " << channel <<endl; 58 cout << "Mode = " << (mode == Antenna ? "antenna":"cable") << endl; //在Tv类和Remote类中都定义了mode 59 cout << "Input = " << (input == DVD ? "DVD":"TV") << endl; 60 } 61 }
1 //use_tv.cpp 2 #include <iostream> 3 #include "tv.h" 4 5 int main() 6 { 7 using std::cout; 8 Tv s42; //此处将调用Tv类中的构造函数,由于Tv类中的构造函数都有默认参数,所以此处相当于省略了参数而使用默认参数,来初始化s42 9 cout<<"Tv对象初始化设置:"<<endl; 10 s42.settings(); //显示设置 11 12 s42.onoff(); //切换开关状态 13 s42.chanup(); //频道加 14 cout<<"使用电视机本身设置后的参数:"<<endl; 15 s42.sttings(); 16 17 Remote grey; //使用Remote类构造函数中的默认参数初始化并创建Remote对象 18 grey.volup(s42); //增大音量 19 grey.volup(s42); //再次增大音量 20 grey.chanup(s42); //频道加 21 grey.set_chan(s42.5); //设置频道5; 22 cout<<"使用遥控器设置后的参数:"<<endl; 23 s42.settings(); 24 25 Tv s58(Tv::On); //使用参数On创建Tv对象s58 26 s58.set_mode(); 27 s58.settings() 28 29 }
原文:https://www.cnblogs.com/YiYA-blog/p/11391716.html