最近在網上看了一些友元的資料,發現你們寫的都很好,想轉載一下文章,但是有幾點不太好(一、敘述的太多了,看完容易忘了【沙米比較容易健忘】 二、只是知識的講解,以爲比較枯燥【哈哈,本身的感覺】)。下面是本身作的一些改進。ios
進入正題啦。下面按照爲什麼須要友元函數友元類?怎麼使用?使用的地方?來講說友元函數的本質。編程
爲何須要友元函數和友元類 框架
你們學過JAVA的話,應該知道其反射的機制吧,經過反射能夠逆向訪問類的私有成員和函數。從而衍生出了Web框架的AOP(面向切面編程)等,極大的方便了開發。函數
JAVA有,並且好用。C++固然也要有的,因而友元函數和友元類就產生了,本質就是類外的其餘函數或其餘類也能夠訪問該類的私有變量。從而實現類之間數據共享。spa
凡事有利就有弊,在使用其時,沒有必要使用,儘可能不要使用,不要過多的破壞面向對象的封裝性。code
優勢:可以提升效率,表達簡單、清晰對象
缺點:友元函數破環了封裝機制,是程序的邏輯變得複雜和混亂。繼承
怎麼使用友元函數和友元類ip
友元函數使用:ci
普通友元函數: 在類A的裏面聲明此友元函數,在類A的外面定義此友元函數(訪問某類的私有成員 )
類B的成員函數做爲類A的友元函數:先定義類B,而後在類A中聲明類B的成員函數爲其友元函數,最後定義類B的成員函數
友元類 :類B的是類A的友元類,在類A中聲明,在類B能夠經過成員(實例化A的對象),訪問A的私有成員
注意:一、友元函數的聲明語句位置與訪問描述(public、private)無關。
二、友元函數經過對象參數訪問私有數據成員
流程以下:
代碼以下:
普通友元函數:
#include <iostream> using namespace std; class friendClass { public: friendClass(int m, int n) { m_a = m; m_b = n; } friend void printClass(friendClass& fcls); //友元函數聲明處 private: int m_a; int m_b; }; void printClass(friendClass& fcls) //友元函數定義處 { cout<<"a="<<fcls.m_a<<" b="<<fcls.m_b<<endl; } int main() { friendClass ff(1,2); printClass(ff); }
類的成員函數作友元函數
注意順序:成員函數做爲友元函數的類定義要在友元函數訪問的類定義以前。
緣由是,只有當一個類的定義已經被看到時它的成員函數才能被聲明爲另外一個類的友元(很重要)
tip:聲明能夠有多處,定義只能有一處,在編譯器已經加載了定義,其餘的聲明才起做用
#include <iostream> using namespace std; class friendClass; class friendFuncClass //成員函數做爲友元函數的類 { public: void printClass(friendClass& fcls); //聲明友元函數 }; class friendClass //友元函數訪問的類 { public: friendClass(int m, int n) { m_a = m; m_b = n; } friend void friendFuncClass::printClass(friendClass& fcls);//聲明友元函數 private: int m_a; int m_b; }; void friendFuncClass::printClass(friendClass& fcls) //定義友元函數 { cout<<"a="<<fcls.m_a<<" b="<<fcls.m_b<<endl; } int main() { friendClass ff(1,2); friendFuncClass fu; fu.printClass(ff); system("pause"); return 0; }
友元類 注意:
(1) 友元關係不能被繼承。
(2) 友元關係是單向的,不具備交換性。若類B是類A的友元,類A不必定是類B的友元,要看在類中是否有相應的聲明。
(3) 友元關係不具備傳遞性。若類B是類A的友元,類C是B的友元,類C不必定是類A的友元,一樣要看類中是否有相應的聲明
#include <iostream> using namespace std; //友元類的使用,類B的是類A的友元類,類B能夠經過成員(實例化A的對象),訪問A的私有成員 class frindAClass { public: frindAClass() { A_a = 1; A_b = 2; } private: int A_a; int A_b; friend class frindBClass; }; class frindBClass { public: frindBClass(frindAClass& fa ):objA(fa) { } void printA() //打印類A的私有成員 { cout<<"a="<<objA.A_a<<" b="<<objA.A_b<<endl; } private: frindAClass objA; }; int main() { //友元類的使用 frindAClass fa; frindBClass fb(fa); fb.printA(); system("pause"); return 0; }
使用的地方
1)運算符重載的某些場合須要使用友元。
如:須要重載輸入輸出運算符(<< 、>>),這個雙目運算符的左側運算量是 cin或 cout,不是對象自己,咱們就只能使用友元函數來訪問對象的私有成員。
2)兩個類要共享數據的時候
最後但願能對你們有幫助,沙米才疏學淺,有什麼錯誤請留言指正,謝謝你們。