生學(xué)C++編程語(yǔ)法知識(shí)(C++中的友元函數(shù)(friend function)))
C中的友元函數(shù)friend function——為什么一個(gè)“外人”可以進(jìn)入類的私密房間同學(xué)們我們以前學(xué)習(xí)過(guò)封裝類把自己的數(shù)據(jù)保護(hù)起來(lái)外面的人不能隨便訪問(wèn)。例如class Student { private: int score; public: Student(int s) { score s; } };這里score是私有成員。外面Student s(100); cout s.score;會(huì)報(bào)錯(cuò)。為什么因?yàn)閜rivate私有成員只允許類自己訪問(wèn)。但是有一天出現(xiàn)一個(gè)特殊情況有一個(gè)“外人”雖然不是這個(gè)類的成員但是特別可靠希望它能夠訪問(wèn) private。怎么辦C提供了friend友元一、什么是友元函數(shù)一句話友元函數(shù)是一個(gè)普通函數(shù)但是類允許它訪問(wèn)自己的私有成員。注意它不是類的成員函數(shù)。它只是普通函數(shù) 特殊權(quán)限例如#include iostream using namespace std; class Student { private: int score; public: Student(int s) { score s; } friend void show(Student s); }; void show(Student s) { cout s.score endl; } int main() { Student stu(100); show(stu); }輸出100為什么因?yàn)殡m然show()不是 Student 的成員函數(shù)。但是Student說(shuō)friend void show(Student s);意思是我允許這個(gè)函數(shù)訪問(wèn)我的秘密。所以s.score可以訪問(wèn)。二、沒(méi)有友元會(huì)怎樣如果沒(méi)有friend那么void show(Student s) { cout s.score; }編譯錯(cuò)誤score is private因?yàn)槠胀ê瘮?shù)沒(méi)有權(quán)限。三、生活中的例子假設(shè)你有一個(gè)小保險(xiǎn)箱。里面private: 金幣 密碼 日記普通同學(xué)不能打開(kāi)。但是你的爸爸你告訴他密碼friend 爸爸于是爸爸可以打開(kāi)。注意爸爸不是保險(xiǎn)箱的一部分。但是擁有特殊權(quán)限。這就是友元。四、友元函數(shù)為什么必須在類里面聲明這是很多初學(xué)者疑惑的問(wèn)題。例如為什么不能class Student { private: int score; }; friend void show(Student s);這樣寫(xiě)答案因?yàn)閒riend是一種“授權(quán)聲明”。授權(quán)必須由擁有東西的人發(fā)出。我們舉生活例子你的房子房主小明。小明說(shuō)我允許張三進(jìn)入我的房子。這個(gè)聲明必須由小明說(shuō)。不能張三自己說(shuō)我宣布我是小明家的朋友所以我可以進(jìn)去。不行。C也是一樣類擁有private成員所以必須由類聲明friend void show(Student s);表示“我允許show訪問(wèn)”。五、友元聲明在哪里寫(xiě)通常寫(xiě)在class內(nèi)部例如class Student { private: int score; public: friend void show(Student s); };位置其實(shí)private下面public下面都可以。例如這樣也可以class Student { public: friend void show(Student s); private: int score; };因?yàn)閒riend聲明不受private/public影響。六、friend聲明只是授權(quán)不代表函數(shù)屬于類這是重點(diǎn)很多學(xué)生容易誤解看到friend void show(Student s);以為show是Student的方法。錯(cuò)誤真正的成員函數(shù)class Student { public: void show(); };調(diào)用stu.show();友元函數(shù)friend void show(Student);調(diào)用show(stu);區(qū)別成員函數(shù)友元函數(shù)屬于類嗎是不是調(diào)用方式對(duì)象.函數(shù)()普通函數(shù)()能訪問(wèn)private嗎可以可以需要friend嗎不需要需要七、為什么需要友元函數(shù)那么問(wèn)題來(lái)了既然破壞封裝為什么還要存在主要有幾個(gè)原因。1. 兩個(gè)類需要互相合作例如有class A { private: int x; }; class B { private: int y; };如果A需要訪問(wèn)B內(nèi)部數(shù)據(jù)。怎么辦可以friend class A;2. 運(yùn)算符重載這是最常見(jiàn)用途。例如我們想cout student;輸出學(xué)生信息。實(shí)際上cout左邊是ostream。不是Student。所以通常寫(xiě)friend ostream operator(ostream, Student);例如class Student { private: int score; public: Student(int s) { scores; } friend ostream operator(ostream out, Student s); }; ostream operator(ostream out, Student s) { outs.score; return out; }使用Student s(99); couts;輸出99八、友元函數(shù)會(huì)破壞封裝嗎這是一個(gè)經(jīng)典問(wèn)題。答案會(huì)降低封裝性但是有時(shí)候非常方便。為什么因?yàn)閜rivate本來(lái)是“不讓別人看”。friend相當(dāng)于“給某個(gè)人開(kāi)后門(mén)”。所以不要大量使用。原則能不用friend就不用friend。 必須合作時(shí)再使用friend。九、友元函數(shù)和成員函數(shù)的區(qū)別考試重點(diǎn)例如class A { private: int x; public: void f(); friend void g(A); };其中f()成員函數(shù)特點(diǎn)a.f();內(nèi)部有隱藏參數(shù)this指針g()友元函數(shù)普通函數(shù)g(a);沒(méi)有this指針十、小學(xué)生記憶口訣 ?什么是友元不是家庭成員 但是擁有鑰匙。為什么類里面聲明誰(shuí)家的秘密 誰(shuí)決定開(kāi)放。friend特點(diǎn)friend不是成員 但是能訪問(wèn)private。不要濫用friend是一把鑰匙 鑰匙越多家越不安全。十一、考點(diǎn)總結(jié)看到friend void fun();記住? fun不是成員函數(shù)? fun可以訪問(wèn)private? 必須在類內(nèi)部聲明? 類外定義? 不需要對(duì)象調(diào)用一句話總結(jié)友元函數(shù)是類授予某個(gè)普通函數(shù)的特殊訪問(wèn)權(quán)限它不是類成員卻可以訪問(wèn)類的private成員。因?yàn)闄?quán)限來(lái)自類本身所以必須由類內(nèi)部進(jìn)行friend聲明而不能由外部自己聲明。這也是 C 面向?qū)ο笾小胺庋b與特殊開(kāi)放”的一個(gè)重要設(shè)計(jì)思想。