friend class

提到友元類,一般會同時提到友元函式。兩者在許可權開放上類似。 採用類的機制後實現了數據的隱藏與封裝,類的數據成員一般定義為私有成員,成員函式一般定義為公有的,依此提供類與外界間的通信接口。但是,有時需要定義一些函式,這些函式不是類的一部分(注意友元函式不是類的一部分),但又需要頻繁地訪問類的數據成員,這時可以將這些函式定義為該函式的友元函式。除了友元函式外,還有友元類,兩者統稱為友元。友元的作用是提高了程式的運行效率(即減少了類型檢查和安全性檢查等都需要時間開銷),但它破壞了類的封裝性和隱藏性,使得非成員函式可以訪問類的私有成員。

友元函式與友元類。

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; }

相關詞條

熱門詞條

聯絡我們