C++友元函數和友元類
<上一節
下一節>
通過friend關鍵字,我們可以將不屬于當前類的一個函數在當前類中加以聲明,該函數便可以成為當前類的友元函數。
例1:
除了頂層函數可以被定義為友元函數之外,其它類的成員函數同樣可以聲明為本類的友元函數,如例2所示。
例2:
這個例子有幾點需要注意一下。首先要注意的是date類的定義必須出現在time類之前,這么做是為了使得display函數的函數聲明能夠在聲明為友元函數之前。其次,display函數的形參為time類對象的引用,而time類又必須定義在date類之后,如此一來只能先將time類聲明在date類之前了,如class time;這一語句即是為了聲明time類。第三點就是需要將display函數的定義放到time類定義的后面,這是因為display函數中必須用到time類中的私有成員變量,因此在使用之前,這些成員變量必須先聲明出來。這三個需要注意順序的地方需要大家特別關注一下,順序一定不能搞錯了,否則都是無法通過編譯的。
無論是類的成員函數還是頂層函數,它們都是可以被多個類聲明為友元函數的,如此一來就可以訪問多個類中的私有成員變量,但是為了保證數據的安全,友元函數的使用寧缺毋濫。
除了可以利用friend關鍵字聲明友元函數之外,我們還可以將其它類聲明為當前類的友元類。友元類聲明的語法非常簡單,即為“friend 類名;”。
例3:
關于友元還有幾點需要注意:
例1:
#include<iostream> using namespace std; class book { public: book(){} book(char* a, double p); friend void display(book &b); private: double price; char * title; }; book::book(char* a, double p) { title = a; price = p; } void display(book &b) { cout<<"The price of "<<b.title<<" is $"<<b.price<<endl; } int main() { book Alice("Alice in Wonderland",29.9); display(Alice); book Harry("Harry potter", 49.9); display(Harry); return 0; }在本例中,display是一個頂層函數,在book類中,我們借助friend關鍵字將其聲明為友元函數,結果,在display函數體內,我們就能訪問private屬性的title和price成員變量。這就是友元函數的作用。友元函數可以訪問這個類中的私有成員。如果這個display函數不是book類的友元函數,則在函數體中還必須調用public屬性的成員函數。在此例中需要注意的是友元函數的形參是類對象的引用,同時在訪問私有成員變量時必須要加上對象名。
除了頂層函數可以被定義為友元函數之外,其它類的成員函數同樣可以聲明為本類的友元函數,如例2所示。
例2:
#include<iostream> using namespace std; class time; class date { public: date(int y,int m,int d); void display(time &t); private: int year; int month; int day; }; class time { public: time(int s,int m,int h); friend void date::display(time & t); private: int second; int minute; int hour; }; time::time(int s,int m,int h) { second = s; minute = m; hour = h; } date::date(int y,int m,int d) { year = y; month = m; day = d; } void date::display(time &t) { cout<<"The time is:"<<endl; cout<<year<<"/"<<month<<"/"<<day<<" "; cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl; } int main() { date d(2015,1,16); time t(20,2,30); d.display(t); return 0; }在本例中定義了兩個類time和date,在time類中有hour、minute和second三個成員變量,分別代表時分秒,在date類中有year、month和day三個成員變量,分別代表年月日信息。為了能夠共同顯示年月日時分秒信息,我們在date類中聲明了一個display函數,并且將該函數設置為time類的友元函數,如此一來,該函數既能訪問date類中的私有成員變量,同時又能訪問time類中的私有成員變量,打印時間自然不在話下。
這個例子有幾點需要注意一下。首先要注意的是date類的定義必須出現在time類之前,這么做是為了使得display函數的函數聲明能夠在聲明為友元函數之前。其次,display函數的形參為time類對象的引用,而time類又必須定義在date類之后,如此一來只能先將time類聲明在date類之前了,如class time;這一語句即是為了聲明time類。第三點就是需要將display函數的定義放到time類定義的后面,這是因為display函數中必須用到time類中的私有成員變量,因此在使用之前,這些成員變量必須先聲明出來。這三個需要注意順序的地方需要大家特別關注一下,順序一定不能搞錯了,否則都是無法通過編譯的。
無論是類的成員函數還是頂層函數,它們都是可以被多個類聲明為友元函數的,如此一來就可以訪問多個類中的私有成員變量,但是為了保證數據的安全,友元函數的使用寧缺毋濫。
除了可以利用friend關鍵字聲明友元函數之外,我們還可以將其它類聲明為當前類的友元類。友元類聲明的語法非常簡單,即為“friend 類名;”。
例3:
#include<iostream> using namespace std; class time; class date { public: date(int y,int m,int d); void display(time &t); private: int year; int month; int day; }; class time { public: friend date; time(int s,int m,int h); private: int second; int minute; int hour; }; time::time(int s,int m,int h) { second = s; minute = m; hour = h; } date::date(int y,int m,int d) { year = y; month = m; day = d; } void date::display(time &t) { cout<<"The time is:"<<endl; cout<<year<<"/"<<month<<"/"<<day<<" "; cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl; } int main() { date d(2015,1,16); time t(20,2,30); d.display(t); return 0; }在本例中,我們將date類聲明為time類的友元類,則此時date類中的所有成員函數都將轉化為time類的友元函數,可以訪問time類中的所有成員。毫無疑問,date類中display函數同樣也會成為time類的友元,因此利用time類對象t的引用便可以訪問time類的私有成員變量了。此函數中類的聲明及定義、函數的聲明及定義位置同樣需要注意。
關于友元還有幾點需要注意:
- 例3中我們將date類聲明為time類的友元類,此時date類中的所有函數都將成為time類的友元函數。
- date類是time類的友元類,但是time類不是date類的友元類。友元關系是單向的,而不是雙向的。如果需要將time類也聲明名為date類的友元類,則需要另外在date類中聲明。
- 友元關系不能傳遞,假設A類是B類的友元類,B類是C類的友元類,這兩點并不能得出A類是C類的友元類。
- 友元類會破壞數據的安全性,使用時寧缺毋濫。如果不是能夠極大提高程序運行效率的情況,最好不要用友元。
<上一節
下一節>