C++中友元的實(shí)例詳解
C++中友元的實(shí)例詳解
盡管友元被授予從外部訪問類的私有部分的權(quán)限,但他們并不與面向?qū)ο蟮木幊趟枷胂嚆?;相反他提高了公共接口的靈活性。
一、友元類
友元聲明可以位于公有、私有活保護(hù)部分、其所在位置無關(guān)緊要
我直接貼出一個摘自< 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 //開關(guān)
};
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; //顯示所有設(shè)置
private:
int state; // 開或者 關(guān)
int volume; // 音量
int maxchannel; //最大
int channel; //當(dāng)前頻道
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 <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;
}
運(yùn)行結(jié)果:
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 請按任意鍵繼續(xù). . .
上述代碼中將Remote類設(shè)置成為了Tv類的友元類,但事實(shí)上我們看到:唯一訪問Tv的成員的方法是void set_chan(Tv &t, int c) { t.channel = c; } ,因此它是唯一需要友元的方法。因此不必讓整個類成為友元,這就引出了我們下面要講的的友元成員函數(shù)。
二、友元成員函數(shù)
我們要再Tv中將Remote::set_chan()設(shè)置成友元:
clas Tv
{
friend void Remote::set_chan(Tv & t,int c ) ;
}
然而要使編譯器能夠處理這條語句,它必須知道Remote的定義。否則,它無法知道Remote是一個類。而 set_chan是這個類的方法。這意味著應(yīng)將Remote的定義放到Tv的定義前面。Remote的方法提到了Tv對象,而意味著Tv定義應(yīng)當(dāng)位于Remote定義之前,避開這種循環(huán)依賴的方法是,使用前向聲明。
所以應(yīng)該這樣:
class Tv ; //前向聲明
class Remote{...}
class Tv {...}
這里還有一個麻煩就是:
Remote 包含了內(nèi)聯(lián)代碼例如:void onoff(Tv &t) {t.onoff();};
由于這將調(diào)用Tv的一個方法,所以編譯器此時已經(jīng)看到了Tv類的聲明,這樣才能知道Tv有哪些方法,但正如看到的,該聲明位于Remote聲明的后面。這種問題的解決方法是:使用Remote聲明中只包含方法聲明,并將實(shí)際的定義放到Tv類之后。 所以最終應(yīng)該這樣:
class Tv; //前向聲明
class Remote {...} //如要用到Tv 只能是方法聲明
class Tv{...}
//接著寫Remote的定義
這里通過方法定義中使用 inline關(guān)鍵字,仍然可以使方法稱為內(nèi)聯(lián)方法
所以程序最終將tv.h改為:
#ifndef TV_H_
#define TV_H_
class Tv; //前向聲明
class Remote {
public:
enum {
off, on //開關(guān)
};
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); //友元成員函數(shù)
enum {
off, on //開關(guān)
};
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; //顯示所有設(shè)置
private:
int state; // 開或者 關(guān)
int volume; // 音量
int maxchannel; //最大
int channel; //當(dāng)前頻道
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_
測試結(jié)果不變。
*另外:也可一個將內(nèi)聯(lián)函數(shù)放在tv.cpp中,但必須去掉inline關(guān)鍵字,這樣函數(shù)的連接性將成為外部的。
三、其他友元關(guān)系
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()是內(nèi)聯(lián)的,則應(yīng)在一個單獨(dú)的方法定義文件中定義它。
2、共同的友元。
需要使用友元的另一種情況是,函數(shù)需要訪問兩個類的私有數(shù)據(jù)。它可以是一個類的友元,同時是另一個類的友元。示例如下:
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)
{
...
}
如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
上一篇:C++中CString string char* char 之間的字符轉(zhuǎn)換(多種方法)
欄 目:C語言
下一篇:C語言中無符號數(shù)和有符號數(shù)之間的運(yùn)算
本文標(biāo)題:C++中友元的實(shí)例詳解
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/1183.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁面的局部加載


