友元函式與友元類。
C++中以關鍵字friend聲明友元關係。友元可以訪問與其有friend關係的類中的私有成員。友元包括友元函式和友元類。
友元函式
如果在本類以外的其它地方定義了一個函式(這個函式可以是不屬於任何類的非成員函式,也可以是其它類的成員函式),在類體中用friend對該函式進行聲明,此函式就稱為本類的友元函式。一個類的友元函式可以訪問這個類中的private成員。
1.1將全局函式聲明為友元函式
如果要將一個全局函式(call)聲明為本類(Time)的友元函式,則只需要在本類的函式聲明部分聲明該函式為friend。此時,該函式可以訪問本類的private成員。
class Time{ public: Time(int=1,int=1,int=1); friendvoid call(Time &);//聲明友元函式 private: int hour; int min; int sec; }; Time::Time(int h,int m,int s){ hour=h; min=m; sec=s; } void call(Time &t) {//全局函式,且是Time類的友元函式 cout<<"Call:"<<t.hour<<"-"<<t.min<<"-"<<t.sec<<endl;//訪問private成員 } int main(){ Time t; call(t); system("PAUSE"); return EXIT_SUCCESS; } |
1.2友元成員函式
如果需要將目標類(Time)中的成員函式(call)聲明為本類(Date)的友元函式,則需要在本類的函式聲明部分聲明該函式為friend。此時,該函式可以訪問本類的private成員。
class Date; //對Date類的提前引用聲明 class Time{ public: Time(int=1,int=1,int=1); void call(Date &);//聲明成員函式 private: int hour; int min; int sec; }; class Date{ public: Date(int=1,int=1,int=2008); friendvoid Time::call(Date&); //聲明Time類的call為本類的友元成員函式 private: int year; int mon; int day; }; Time::Time(int h,int m,int s){ hour=h; min=m; sec=s; } void Time::call(Date &d) { cout<<"TIME:"<<hour<<"-"<<min<<"-"<<sec<<endl; cout<<"DATE:"<<d.mon<<"-"<<d.day<<"-"<<d.year<<endl; //訪問Date類的private成員 } Date::Date(int m,int d,int y){ mon=m; day=d; year=y; } int main(){ Time t; Date d; t.call(d); system("PAUSE"); return EXIT_SUCCESS; } |
這裡還做了對類的提前引用聲明。
1.3關於類的提前引用聲明
一般情況下,類必須先聲明(給出類體),才能使用。如果需要在類聲明之前,使用該類的名字去定義指向該類對象的指針或引用,可以使用提前引用聲明。如上例所示,
class Date; //對Date類的提前引用聲明 … void call(Date &);//Date類的引用 … class Date{…}//Date類的聲明 |
但不能因為提前引用聲明,而去定義一個類的對象,這是不允許的。
class Date; //緊接著馬上定義一個Date類的對象 Date d1;error:aggregate `Date d1' has incomplete type and cannot be defined … class Date{…} |
在定義對象時要為這些對象分配存儲空間,在正式聲明類之前,編譯系統無法確定應為對象分配多大的存儲空 間。編譯系統只有見到“類體”之後才能確定應該為對象預留多大的空間。所以不能在聲明類之前,先定義一個該類的對象。但是可以在聲明類之前,先使用該類的 名字定義一個該類的指針或引用。因為指針變數和引用本身的大小是固定的,它與指向的類對象的大小無關。
1.4將一個函式聲明為多個類的友元函式
在這種情況下,該函式可以同時訪問多個類的private成員。
class Date; //對Date類的提前引用聲明 class Time{ public: Time(int=1,int=1,int=1); friendvoid call(Time&,Date&);//聲明函式call為本類的友元成員函式 private: int hour; int min; int sec; }; class Date{ public: Date(int=1,int=1,int=2008); friendvoid call(Time&,Date&); //聲明函式call為本類的友元成員函式 private: int year; int mon; int day; }; Time::Time(int h,int m,int s){ hour=h; min=m; sec=s; } Date::Date(int m,int d,int y){ mon=m; day=d; year=y; } void call(Time &t,Date &d) { cout<<"TIME:"<<t.hour<<"-"<<t.min<<"-"<<t.sec<<endl; cout<<"DATE:"<<d.mon<<"-"<<d.day<<"-"<<d.year<<endl; } int main(){ Time t; Date d; call(t,d); system("PAUSE"); return EXIT_SUCCESS; } |
友元類
可以將一個類(B)聲明為當前類(A)的友元。此時,當前類(A)的友元類(B)中的所有成員函式都是當前類的友元函式,可以訪問當前類的private成員。
class Date; //對Date類的提前引用聲明 class Time{ public: Time(int=1,int=1,int=1); friendclass Date;//將Date類聲明為當前類的友元類 private: int hour; int min; int sec; }; class Date{ public: Date(int=1,int=1,int=2008); void call_hour(Time&); void call_min(Time&); void call_sec(Time&); private: int year; int mon; int day; }; Time::Time(int h,int m,int s){ hour=h; min=m; sec=s; } Date::Date(int m,int d,int y){ mon=m; day=d; year=y; } void Date::call_hour(Time &t){ cout<<"HOUR:"<<t.hour<<endl; } void Date::call_min(Time &t){ cout<<"MINUTE:"<<t.min<<endl; } void Date::call_sec(Time &t){ cout<<"SECOND:"<<t.sec<<endl; } int main(){ Time t; Date d; d.call_hour(t); d.call_min(t); d.call_sec(t); system("PAUSE"); return EXIT_SUCCESS; } |