在某些情況下,類別將不屬於類別成員的函式,或授與個別類別中所有成員的成員層級存取權會很有用。 這些免費函式和類別稱為 friend,並以 關鍵詞標示 friend 。 只有類別實作器可以宣告其朋友是誰。 函式或類別無法將自己宣告為任何類別的朋友。 在類別定義中,使用 friend 非member函式或其他類別的 關鍵詞和名稱,將類別的私人和受保護成員的存取權授與它。 在樣本定義中,類型參數可以宣告為 friend。
語法
friend-declaration:
friend
function-declaration
friend
function-definition
friend
elaborated-type-specifier
;;
friend
simple-type-specifier
;
friend
typename-specifier
;
friend 聲明
如果您宣告 friend 先前未宣告的函式,該函式會匯出至封入的非類別範圍。
宣告中 friend 宣告的函式會被視為使用 extern 關鍵詞宣告的函式。 如需詳細資訊,請參閱extern。
雖然具有全域範圍的函式可以在原型之前宣告為 friend 函式,但是成員函式無法在完整類別宣告的外觀之前宣告為 friend 函式。 下列程式代碼顯示這類宣告如何失敗:
class ForwardDeclared; // Class name is known.
class HasFriends
{
friend int ForwardDeclared::IsAFriend(); // C2039 error expected
};
上述範例會將類別名稱 ForwardDeclared 輸入範圍,但不知道完整宣告(特別是宣告 IsAFriend函式的部分)。 類別friendHasFriends中的宣告會產生錯誤。
在 C++11 中,類別有兩種形式的 friend 宣告:
friend class F;
friend F;
第一個窗體會在最內層命名空間中找到該名稱的現有類別時,引進新的類別 F。
C++11:第二個窗體不會引進新的類別;當類別已經宣告時可以使用,而且在宣告樣板類型參數或 typedef 做為 friend時必須使用它。
當參考的類型尚未宣告時使用 friend class F :
namespace NS
{
class M
{
friend class F; // Introduces F but doesn't define it
};
}
如果您搭配未宣告的類別類型使用 friend ,就會發生錯誤:
namespace NS
{
class M
{
friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
};
}
在下列範例中, friend F 是指 F 在 NS 範圍之外宣告的 類別。
class F {};
namespace NS
{
class M
{
friend F; // OK
};
}
使用 friend F 將範本參數宣告為friend:
template <typename T>
class my_class
{
friend T;
//...
};
使用 friend F 將 typedef 宣告為 friend:
class Foo {};
typedef Foo F;
class G
{
friend F; // OK
friend class F // Error C2371 -- redefinition
};
若要宣告兩個類別是彼此的朋友,必須將整個第二個類別指定為第一類的朋友。 此限制的原因是編譯程式有足夠的資訊,只能在宣告第二個類別的點宣告個別friend函式。
備註
雖然整個第二類必須是第一類的朋友,但您可以選取第一類中的哪些函式將是第二類的朋友。
friend 函式
函 friend 式不是類別的成員,但可以存取類別的私人和受保護的成員。 Friend 函式不會被視為類別成員;它們是一般外部函式,提供特殊存取許可權。 Friend 不在類別的範圍中,除非是另一個類別的成員,否則不會使用成員選取運算符 (和 ->) 來呼叫。 函 friend 式是由授與存取權的類別所宣告。 宣告 friend 可以放在類別宣告中的任何位置。 它不會受到訪問控制關鍵詞的影響。
下列範例顯示 Point 類別和friend 函式 ChangePrivate。 函 friend 式可以存取其接收做為參數之 Point 物件的私用數據成員。
// 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
}
以朋友身分的類別成員
類別成員函式可以宣告為其他類別中的friend。 請考慮下列範例:
// 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
在上述範例中 A::Func1( B& ) ,只會將 函式的存取權授與 friend 類別 B。 因此,在類別A中Func1存取私用成員_b是正確的,但在 中Func2則不是 。
類別 friend 是類別,其成員函式都是 friend 類別的函式,也就是說,其成員函式可以存取其他類別的私人和受保護的成員。
friend假設 類別B中的宣告是:
friend class A;
在此情況下,類別中的所有 A 成員函式都會被授與 friend 類別的 B存取權。 下列程式代碼是 類別 friend 的範例:
// 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();
}
除非明確指定為,否則友誼不是相互的。 在上述範例中,的成員 YourClass 函式無法存取 的私用 YourOtherClass成員。
Managed 類型 (在 C++/CLI 中) 不能有任何 friend 函式、 friend 類別或 friend 介面。
友誼不會繼承,這表示衍生自 YourOtherClass 的類別無法存取 YourClass的私用成員。 友誼不是可轉移的,所以那些是朋友 YourOtherClass 的班級無法存取 YourClass的私人成員。
下圖顯示四個類別宣告: Base、 Derived、 aFriend和 anotherFriend。 只有類別 aFriend 可以直接存取 的私用成員 Base (以及可能繼承的任何成員 Base )。
此圖顯示另一個朋友的類別與朋友類類別的類別基底沒有朋友關係。 類別 AFriend 是由類別基底所交友,但即使類別 Derived 繼承自 Base,它也沒有與衍生類別的 friend 關聯性。 這示範繼承並不表示衍生類別與基類具有相同的朋友。
內嵌 friend 定義
Friend 函式可以在類別宣告內定義(指定函式主體)。 這些函式是內嵌函式。 如同成員內嵌函式,它們的行為就像是在看到所有類別成員之後立即定義,但在類別範圍關閉之前(在類別宣告的結尾)。 類別宣告內定義的Friend函式位於封入類別的範圍內。