本文基於《C++ Primer(第五版)》,純屬個人筆記整理。若有錯誤歡迎大家留言指出。
一、為什么要用友元和其缺點?
采用類的機制后實現了數據的隱藏與封裝,類的數據成員一般定義為私有成員,成員函數一般定義為公有的,依此提供類與外界間的通信接口。有時候,其他類或者函數要訪問該類的非公有成員,可以令其他類或者函數成為它的友元(friend)來實現。這樣做提高了程序的運行效率,但同時也壞了類的封裝性和隱藏性,使得非成員函數或其他類可以訪問類的私有成員。
二、友元函數
友元定義格式如下:
friend 類型 函數名(形參);
首先,友元函數可以訪問類的私有成員,其本身是定義在類外的普通函數,但是友元聲明只能出現在類定義的內部,同時因為,友元不是類的成員也不受它所在區域訪問控制級別的約束,其出現的位置不定,即既可以出現在private下也可以在public下;其次,若類想把一個函數作為它的友元,只需增加一條以friend關鍵字開頭的函數聲明語句即可。如:
1 class Sales_data 2 { 3 friend Sales_data add(const Sales_data&,const Sales_data&); //定義友元函數 4 ...... 5 }; 6 7 /*非成員函數的聲明*/ 8 Sales_data add(const Sales_data&,const Sales_data&);
這里值得注意的幾點是:
(1)友元的聲明僅僅指定了訪問的權限,而非一個通常意義上的函數聲明,如果我們希望類的用戶能夠調用某個友元函數,那么我們就必須在友元聲明之外再專門針對函數進行一次聲明。為了使友元對類的用戶可見,我們通常把友元的聲明與類的本身放置在同一個頭文件中(類的外部)。
(2)友元函數的調用與一般函數的調用方式和原理一致。
(3)類和非成員函數的聲明不是必須在它們的友元聲明之前。
(4)友元函數能定義在類的內部,這樣的函數是隱式內聯的。
三、友元類
1、類之間的友元關系
如果希望一個類可以訪問另一個類的非公有成員在內的所有成員(主要是非公有的成員),可以將一個類指定為另一類的友元類。
如將類B定義為類A的友元類:
1 class A 2 { 3 .......//省略其他 4 private: 5 friend class B; 6 };
這里使用友元類有幾點要注意的:
(1)友元關系不存在傳遞性,即每個類負責控制自己的友元類或者友元函數;
(2)友元關系是單向的,不具有交換性。若類B是類A的友元,類A不一定是類B的友元,要看在類中是否有相應的聲明。
(3)友元關系不能被繼承。
2、成員函數作為友元
即一個類的成員函數作為另一個類的友元。此時,我們必須指出該成員函數屬於哪個類。
1 class A 2 { 3 .......//省略其他 4 private: 5 friend void B::add(a,b); 6 }
這里指明函數add是類B的成員函數。
這里有一點要注意的是 B::add必須在A類之前被聲明;
Ref: