剖析C++編程中friend關(guān)鍵字所修飾的友元函數(shù)和友元類(lèi)
在某些情況下,為不是類(lèi)成員的函數(shù)或單獨(dú)類(lèi)中的所有函數(shù)授予成員級(jí)別的訪問(wèn)權(quán)會(huì)更方便。僅類(lèi)實(shí)現(xiàn)器可以聲明其友元。函數(shù)或類(lèi)不能將其自身聲明為任何類(lèi)的友元。在類(lèi)聲明中,使用 friend 關(guān)鍵字和非成員函數(shù)名稱或其他類(lèi),以允許其訪問(wèn)你的類(lèi)的專(zhuān)用和受保護(hù)成員。
語(yǔ)法
friend class-name; friend function-declarator;
友元聲明
如果聲明以前未聲明的友元函數(shù),則該函數(shù)將被導(dǎo)出到封閉非類(lèi)范圍。
友元聲明中聲明的函數(shù)被視為已使用 extern 關(guān)鍵字聲明。(有關(guān) extern 的詳細(xì)信息,請(qǐng)參閱靜態(tài)存儲(chǔ)類(lèi)說(shuō)明符。)
盡管具有全局范圍的函數(shù)可以在其原型之前聲明為友元函數(shù),但是成員函數(shù)在它們的完整類(lèi)聲明出現(xiàn)前不能聲明為友元函數(shù)。以下代碼演示此失敗的原因:
class ForwardDeclared; // Class name is known. class HasFriends { friend int ForwardDeclared::IsAFriend(); // C2039 error expected };
前面的示例將類(lèi)名 ForwardDeclared 輸入到范圍中,但是完整的聲明(具體而言,聲明函數(shù) IsAFriend 的部分)是未知的。因此,friend 類(lèi)中的 HasFriends 聲明會(huì)生成一個(gè)錯(cuò)誤。
若要聲明兩個(gè)互為友元的類(lèi),則必須將整個(gè)第二個(gè)類(lèi)指定為第一個(gè)類(lèi)的友元。此限制的原因是該編譯器僅在聲明第二個(gè)類(lèi)的位置有足夠的信息來(lái)聲明各個(gè)友元函數(shù)。
注意
盡管整個(gè)第二個(gè)類(lèi)必須是第一個(gè)類(lèi)的友元,但是可以選擇將第一個(gè)類(lèi)中的哪些函數(shù)作為第二個(gè)類(lèi)的友元。
友元函數(shù)
friend 函數(shù)是一個(gè)不為類(lèi)成員的函數(shù),但它可以訪問(wèn)類(lèi)的私有和受保護(hù)的成員。友元函數(shù)不被視為類(lèi)成員;它們是獲得了特殊訪問(wèn)權(quán)限的普通外部函數(shù)。友元不在類(lèi)的范圍內(nèi),除非它們是另一個(gè)類(lèi)的成員,否則不會(huì)使用成員選擇運(yùn)算符(. 和 –>)調(diào)用它們。 friend 函數(shù)由授予訪問(wèn)權(quán)限的類(lèi)聲明。可將 friend 聲明放置在類(lèi)聲明中的任何位置。它不受訪問(wèn)控制關(guān)鍵字的影響。
以下示例顯示 Point 類(lèi)和友元函數(shù) ChangePrivate。 friend 函數(shù)可以訪問(wèn)其接受為參數(shù)的 Point 對(duì)象的私有數(shù)據(jù)成員。
// friend_functions.cpp // compile with: /EHsc #include <iostream> using namespace std; class Point { friend void ChangePrivate( Point & ); public: Point( void ) : m_i(0) {} void PrintPrivate( void ){cout << m_i << endl; } private: int m_i; }; void ChangePrivate ( Point &i ) { i.m_i++; } int main() { Point sPoint; sPoint.PrintPrivate(); ChangePrivate(sPoint); sPoint.PrintPrivate(); // Output: 0 1 }
類(lèi)成員函數(shù)可以聲明為其他類(lèi)中的友元。請(qǐng)看下面的示例:
// classes_as_friends1.cpp // compile with: /c class B; class A { public: int Func1( B& b ); private: int Func2( B& b ); }; class B { private: int _b; // A::Func1 is a friend function to class B // so A::Func1 has access to all members of B friend int A::Func1( B& ); }; int A::Func1( B& b ) { return b._b; } // OK int A::Func2( B& b ) { return b._b; } // C2248
在前面的示例中,僅為函數(shù) A::Func1( B& ) 授予對(duì)類(lèi) B 的友元訪問(wèn)權(quán)限。因此,訪問(wèn)私有成員 _b 在類(lèi) Func1 的 A 中是正確的,但在 Func2 中是不正確的。
friend 類(lèi)是其所有成員函數(shù)都是類(lèi)的友元函數(shù)的類(lèi),即,其成員函數(shù)具有對(duì)類(lèi)的私有成員和受保護(hù)成員訪問(wèn)權(quán)限。假定類(lèi) friend 中的 B 聲明是:
friend class A;
在這種情況下,將為類(lèi) A 中所有成員函數(shù)授予對(duì)類(lèi) B 的友元訪問(wèn)權(quán)限。以下代碼是友元類(lèi)的示例:
// classes_as_friends2.cpp // compile with: /EHsc #include <iostream> using namespace std; class YourClass { friend class YourOtherClass; // Declare a friend class public: YourClass() : topSecret(0){} void printMember() { cout << topSecret << endl; } private: int topSecret; }; class YourOtherClass { public: void change( YourClass& yc, int x ){yc.topSecret = x;} }; int main() { YourClass yc1; YourOtherClass yoc1; yc1.printMember(); yoc1.change( yc1, 5 ); yc1.printMember(); }
友元關(guān)系不是相互的,除非如此顯式指定。在上面的示例中,YourClass 的成員函數(shù)無(wú)法訪問(wèn) YourOtherClass 的私有成員。
托管類(lèi)型不能具有任何友元函數(shù)、友元類(lèi)或友元接口。
友元關(guān)系不能繼承,這意味著從 YourOtherClass 派生的類(lèi)不能訪問(wèn) YourClass 的私有成員。友元關(guān)系不可傳遞,因此 YourOtherClass 的友元類(lèi)無(wú)法訪問(wèn) YourClass 的私有成員。
下圖顯示了 4 個(gè)類(lèi)聲明:Base、Derived、aFriend 和 anotherFriend。只有類(lèi) aFriend 具有對(duì) Base 的私有成員(以及對(duì) Base 可能已繼承的所有成員)的直接訪問(wèn)權(quán)限。
內(nèi)聯(lián)友元定義
可以在類(lèi)聲明中定義友元函數(shù)。這些函數(shù)是內(nèi)聯(lián)函數(shù),類(lèi)似于成員內(nèi)聯(lián)函數(shù),其行為就像它們?cè)谒蓄?lèi)成員顯示后但在類(lèi)范圍關(guān)閉前(類(lèi)聲明的結(jié)尾)被定義時(shí)的行為一樣。
類(lèi)聲明中定義的友元函數(shù)不被認(rèn)為在封閉類(lèi)的范圍內(nèi);它們?cè)谖募秶鷥?nèi)。
上一篇:C++編程指向成員的指針以及this指針的基本使用指南
欄 目:C語(yǔ)言
下一篇:結(jié)合C++11的新特性來(lái)解析C++中的枚舉與聯(lián)合
本文標(biāo)題:剖析C++編程中friend關(guān)鍵字所修飾的友元函數(shù)和友元類(lèi)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2532.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類(lèi)算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)