• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

C++中友元的实例详解

c++ 搞代码 4年前 (2022-01-06) 13次浏览 已收录 0个评论

这篇文章主要介绍了C++中友元的实例详解的相关资料,希望通过本文大家能掌握友元的使用方法,需要的朋友可以参考下

C++中友元的实例详解

尽管友元被授予从外部访问类的私有部分的权限,但他们并不与面向对象的编程思想相悖;相反他提高了公共接口的灵活性。

一、友元类

友元声明可以位于公有、私有活保护部分、其所在位置无关紧要

我直接贴出一个摘自的例子来演示 c++ 友元类

其中 Remote 为 Tv的友元类。

Tv.h

 #ifndef TV_H_ #define TV_H_ /*一个类 电视 */ class Tv { public: friend class Remote; //Remote类可以访问Tv Privite 的私有部分 enum { off,on  //开关 }; enum { MinVal,MaxVal=20  //音量 }; enum { Antena,Cable //使用的天线、还是电缆 }; enum { TV ,DVD  //工作模式 }; Tv(int s = off, int mc = 125) :state(s), volume(5), maxchannel(mc), channel(5), 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 == Antena) ? Cable : Antena; } void set_input() { input = (input == TV) ? DVD : TV; } void settings()const; //显示所有设置 private: int state;  // 开或者 关 int volume; // 音量 int maxchannel; //最大 int channel;  //当前频道 int mode;  // 广播还是 电缆 int input; //Tv 或者 DVD }; /*Remote 的定义 (遥控器) */ class Remote { private : int mode; // 控制 TV 或 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) { return t.onoff(); } void chanup(Tv & t) { return t.chanup(); } void chandown(Tv & t) { return t.chandown(); } void set_chan(Tv &t, int c) { t.channel = c; } //访问了Tv的私有成员 void set_mode(Tv &t) { t.set_mode(); } void set_input(Tv &t) { t.set_input(); } }; #endif // TV_H_ 

Tv.cpp

 #include "stdafx.h" #include "Tv.h" #include  bool Tv::volup() { if (volume  MinVal) { volume--; return true; } else { return false; } } void Tv::chanup() { 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 == Antena ? "antenna" : "cable") << endl; cout << "Input = " << (input == TV ? "TV" : "DVD") << endl; } } 

测试代码:

 #include "stdafx.h" #include "tv.h" #include  int main() { using std::cout; Tv s42; cout << "Initial settings for 42 \" Tv: \n"; s42.settings(); s42.onoff(); s42.chanup(); cout << " \n Adjusted settings for 42 \" Tv: \n"; s42.chanup(); cout << "\n Adjusted settings for 42 \" Tv: \n"; s42.settings(); Remote grey; grey.set_chan(s42, 10); grey.volup(s42); grey.volup(s42); cout << " \n s42 \" settings after using remote: \n"; s42.settings(); Tv s58(Tv::on); s58.set_mode(); grey.set_chan(s58, 58); cout << " \n s58 \" setting: \n"; s58.settings(); system("pause"); return 0; } 

运行结果:

 Initial settings for 42 " Tv: TV is off Adjusted settings for 42 " Tv: Adjusted settings for 42 " Tv: TV is on Volume setting =5 Channel setting = 7 Mode = cable Input = TV s42 " settings after using remote: TV is on Volume setting =7 Channel setting = 10 Mode = cable Input = TV s58 " setting: TV is on Volume setting =5 Channel setting = 58 Mode = antenna Input = TV 请按任意键继续. . . 

上述代码中将Remote类设置成为了Tv类的友元类,但事实上我们看到:唯一访问Tv的成员的方法是void set_chan(Tv &t, int c) { t.channel = c; } ,因此它是唯一需要友元的方法。因此不必让整个类成为友元,这就引出了我们下面要讲的的友元成员函数。

二、友元成员函数

我们要再Tv中将Remote::set_chan()设置成友元:

 clas Tv { friend void Remote::set_chan(Tv & t,int c ) ; } 

然而要使编译器能够处来源gao@daima#com搞(%代@#码网理这条语句,它必须知道Remote的定义。否则,它无法知道Remote是一个类。而 set_chan是这个类的方法。这意味着应将Remote的定义放到Tv的定义前面。Remote的方法提到了Tv对象,而意味着Tv定义应当位于Remote定义之前,避开这种循环依赖的方法是,使用前向声明。
所以应该这样:

 class Tv ; //前向声明 class Remote{...} class Tv {...} 

这里还有一个麻烦就是:

Remote 包含了内联代码例如:void onoff(Tv &t) {t.onoff();};

由于这将调用Tv的一个方法,所以编译器此时已经看到了Tv类的声明,这样才能知道Tv有哪些方法,但正如看到的,该声明位于Remote声明的后面。这种问题的解决方法是:使用Remote声明中只包含方法声明,并将实际的定义放到Tv类之后。 所以最终应该这样:

 class Tv; //前向声明 class Remote {...} //如要用到Tv 只能是方法声明 class Tv{...} //接着写Remote的定义 

这里通过方法定义中使用 inline关键字,仍然可以使方法称为内联方法
所以程序最终将tv.h改为:

 #ifndef TV_H_ #define TV_H_ class Tv; //前向声明 class Remote { public: enum { off, on  //开关 }; enum { MinVal, MaxVal = 20  //音量 }; enum { Antena, Cable //使用的天线、还是电缆 }; enum { TV, DVD  //工作模式 }; private: int mode; // 控制 TV 或 DVD public: Remote(int m = TV) :mode(m) {} //用到了Tv 只能是声明 bool volup(Tv & t); bool voldown(Tv & t); void onoff(Tv & t); void chanup(Tv & t); void chandown(Tv & t); void set_chan(Tv &t, int c); void set_mode(Tv &t); void set_input(Tv &t); }; class Tv { public: friend void Remote::set_chan(Tv & t,int c); //友元成员函数 enum { off, on  //开关 }; enum { MinVal, MaxVal = 20  //音量 }; enum { Antena, Cable //使用的天线、还是电缆 }; enum { TV, DVD  //工作模式 }; Tv(int s = off, int mc = 125) :state(s), volume(5), maxchannel(mc), channel(5), 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 == Antena) ? Cable : Antena; } void set_input() { input = (input == TV) ? DVD : TV; } void settings()const; //显示所有设置 private: int state;  // 开或者 关 int volume; // 音量 int maxchannel; //最大 int channel;  //当前频道 int mode;  // 广播还是 电缆 int input; //Tv 或者 DVD }; inline bool Remote::volup(Tv & t) { return t.volup(); } inline bool Remote::voldown(Tv & t) { return t.voldown(); } inline void Remote::onoff(Tv & t) { return t.onoff(); } inline void Remote::chanup(Tv & t) { return t.chanup(); } inline void Remote::chandown(Tv & t) { return t.chandown(); } inline void Remote::set_chan(Tv &t, int c) { t.channel = c; } inline void Remote::set_mode(Tv &t) { return t.set_mode(); } inline void Remote::set_input(Tv &t) { return t.set_input(); } #endif // TV_H_ 

测试结果不变。

*另外:也可一个将内联函数放在tv.cpp中,但必须去掉inline关键字,这样函数的连接性将成为外部的。

三、其他友元关系

1、上面的代码表示的是Remote是Tv的友元。但我们有时也会用到2个类互相友元。即Remote是Tv的友元,同时 Tv又是Remote的友元

他们定义与下面类似:

 class Remote class Tv { friend clas Remote public: void buzz(Remote & r) ; ... } class Remote { friend class Tv; public: void Bool volup(Tv & t){t.volup();} ... } inline void Tv::buzz(Remote & r) { ... } 

由于Remote的声明位于Tv声明的后面,所以可以在类的定义Remote::volup(),但Tv::buzz()方法必须在Tv声明的外部定义,使其位于Remote声明的外面。如果不希望buzz()是内联的,则应在一个单独的方法定义文件中定义它。

2、共同的友元。

需要使用友元的另一种情况是,函数需要访问两个类的私有数据。它可以是一个类的友元,同时是另一个类的友元。示例如下:

 class Analyzer; class Probe { friend void sync (Analyzer & a,const Probe & p) ; friend void sync (Probe & p,const Analyzer & a); ... }; class Analyzer { friend void sync (Analyzer & a,const Probe & p) ; friend void sync (Probe & p,const Analyzer & a); } inline void sync (Analyzer & a,const Probe & p) { ... } inline void sync (Probe & p,const Analyzer & a) { ... } 

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

以上就是C++中友元的实例详解的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:C++中友元的实例详解

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址