国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++中友元的實例詳解

2020-01-26 13:55:59
字體:
來源:轉載
供稿:網友

C++中友元的實例詳解

盡管友元被授予從外部訪問類的私有部分的權限,但他們并不與面向對象的編程思想相悖;相反他提高了公共接口的靈活性。

一、友元類

友元聲明可以位于公有、私有活保護部分、其所在位置無關緊要

我直接貼出一個摘自< c++ primer plus >的例子來演示 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 或 DVDpublic:  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 <iostream>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 == Antena ? "antenna" : "cable") << endl;    cout << "Input = " << (input == TV ? "TV" : "DVD") << endl;  }}

測試代碼:

#include "stdafx.h"#include "tv.h"#include <iostream>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 onVolume setting =5Channel setting = 7Mode = cableInput = TV s42 " settings after using remote:TV is onVolume setting =7Channel setting = 10Mode = cableInput = TV s58 " setting:TV is onVolume setting =5Channel setting = 58Mode = antennaInput = 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 ) ;}

然而要使編譯器能夠處理這條語句,它必須知道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 或 DVDpublic:  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 Remoteclass Tv{friend clas Remotepublic:  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){  ...}

如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武穴市| 莎车县| 乐至县| 枣庄市| 江津市| 荆门市| 安达市| 莱芜市| 寻乌县| 峨眉山市| 邢台市| 扬州市| 黑龙江省| 娱乐| 池州市| 葫芦岛市| 闻喜县| 同仁县| 青铜峡市| 工布江达县| 鄂伦春自治旗| 马鞍山市| 文成县| 揭阳市| 嘉禾县| 宝山区| 十堰市| 会泽县| 合江县| 江安县| 云阳县| 新邵县| 嘉鱼县| 海兴县| 宁强县| 界首市| 若尔盖县| 陆良县| 隆子县| 莱芜市| 绥棱县|