1爲何要使用友元函數
在實現類之間數據共享時,減小系統開銷,提升效率。若是類A中的函數要訪問類B中的成員(例如:智能指針類的實現),那麼類A中該函數要是類B的友元函數。具體說:爲了
使其餘類的成員函數直接訪問該類的私有變量。即:容許外面的類或函數去訪問類的私有變量和保護變量,從而使兩個類共享同一函數。
實際上具體大概有下面兩種狀況須要使用友元函數:(1)運算符重載的某些場合須要使用友元。(2)兩個類要共享數據的時候。ios
使用友元函數的優缺點
優勢:可以提升效率,表達簡單、清晰。
缺點:友元函數破環了封裝機制,儘可能不使用成員函數,除非不得已的狀況下才使用友元函數。函數
2.友元函數的使用this
友元函數的參數:
由於友元函數沒有this指針,則參數要有三種狀況:
要訪問非static成員時,須要對象作參數
要訪問static成員或全局變量時,則不須要對象作參數;
若是作參數的對象是全局對象,則不須要對象作參數;spa
友元函數的位置
由於友元函數是類外的函數,因此它的聲明能夠放在類的私有段或公有段且沒有區別。指針
友元函數的調用
能夠直接調用友元函數,不須要經過對象或指針對象
友元函數的分類:
根據這個函數的來源不一樣,能夠分爲三種方法:blog
普通函數友元函數繼承
目的:使普通函數可以訪問類的友元io
語法:
聲明: friend + 普通函數聲明
實現位置:能夠在類外或類中
實現代碼:與普通函數相同
調用:相似普通函數,直接調用class
代碼:
class Interger { friend void Print(const INTEGER& obj);//聲明友元函數 }; void Print(const INTEGER& obj) { //函數體 } void main() { Interger obj; Print(obj);//直接調用 }
類Y的全部成員函數都爲類X友元函數—友元類
目的:使用單個聲明使Y類的全部函數成爲類X的友元,它提供一種類之間合做的一種方式,使類Y的對象能夠具備類X和類Y的功能。
語法:
聲明位置:公有私有都可,常寫爲私有(把類當作一個變量)
聲明: friend + 類名(不是對象哦)
代碼:
class girl; class boy { public: void disp(girl &); }; void boy::disp(girl &x) //函數disp()爲類boy的成員函數,也是類girl的友元函數 { cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl;//藉助友元,在boy的成員函數disp中,藉助girl的對象,直接訪問girl的私有變量 } class girl { private: char *name; int age; friend boy; //聲明類boy是類girl的友元 };
類Y的一個成員函數爲類X的友元函數
目的:使類Y的一個成員函數成爲類X的友元,具體而言:在類Y的這個成員函數中,藉助參數X,能夠直接以X的私有變量
語法:
聲明位置:聲明在公有中 (自己爲函數)
聲明:friend + 成員函數的聲明
調用:先定義Y的對象y---使用y調用本身的成員函數---本身的成員函數中使用了友元機制
代碼:
實現代碼和上一代碼中的實現及其類似只是設置友元的時候變爲friend void boy::disp(girl &);
小結:其實一些操做符的重載實現也是要在類外實現的,那麼一般這樣的話,聲明爲類的友元是必須滴。
友元函數和類的成員函數的區別
成員函數有this指針,而友元函數沒有this指針。
友元函數是不能被繼承的,就像父親的朋友未必是兒子的朋友。
友元函數
代碼:
/// /// @file friendfunc.cc /// @author Burgess Fan(1406832037@qq.com) /// @date 2016-06-20 20:38:18 /// #include <iostream> using namespace std; class SalesData{ friend void PrintInfo(SalesData &sdata); public: SalesData(const char*s,unsigned int n,double p) :BookNum(s) ,SaleNum(n) ,BookPrice(p) { cout<<"SalesData()"<<endl; } ~SalesData() { cout<<"~SalesData"<<endl; } private: const char* BookNum; unsigned int SaleNum; double BookPrice; }; void PrintInfo(SalesData &sdata){ cout<<"BookNum is:"<<sdata.BookNum<<endl; cout<<"SaleNum is:"<<sdata.SaleNum<<endl; cout<<"BookPrice is:"<<sdata.BookPrice<<endl; } int main(void){ SalesData s("2016006",10,20.5); PrintInfo(s); return 0; }