friend
(C++)
在某些情況下,類別將不屬於類別成員的函式,或授與個別類別中所有成員的成員層級存取權會很有用。 這些免費函式和類別稱為 friend ,並以 關鍵字標示 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
函式的部分)。 類別 friend
HasFriends
中的宣告會產生錯誤。
在 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
式不是類別的成員,但可以存取類別的私人和受保護的成員。 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 的類別成員
類別成員函式可以宣告為其他類別的 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
的 private 成員 (以及 Base
可能繼承的任何成員)。
此圖顯示另一個朋友的類別與朋友類類別的類別基底沒有朋友關係。 類別 AFriend 是由類別基底所交友,但即使類別 Derived 繼承自 Base,它也沒有與衍生類別的 friend 關聯性。 這示範繼承並不表示衍生類別與基類具有相同的朋友。
內嵌 friend
定義
Friend 函式可以在類別宣告內定義(指定函式主體)。 這些函式是內嵌函式。 如同成員內嵌函式,它們的行為就像是在看到所有類別成員之後立即定義,但在類別範圍關閉之前(在類別宣告的結尾)。 類別宣告內定義的 Friend 函式位於封入類別的範圍內。
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應