friend
(C++)
W niektórych okolicznościach warto przyznać klasie dostęp na poziomie składowym do funkcji, które nie są członkami klasy lub do wszystkich składowych w oddzielnej klasie. Te bezpłatne funkcje i klasy są znane jako przyjaciele, oznaczone friend
słowem kluczowym. Tylko implementator klasy może zadeklarować, kim są jego przyjaciele. Funkcja lub klasa nie może zadeklarować się jako przyjaciel jakiejkolwiek klasy. W definicji klasy użyj friend
słowa kluczowego i nazwy funkcji nieczłonkowej lub innej klasy, aby udzielić mu dostępu do prywatnych i chronionych składowych klasy. W definicji szablonu parametr typu można zadeklarować jako friend
.
Składnia
friend-declaration
:
friend
function-declaration
friend
function-definition
friend
elaborated-type-specifier
;
;
friend
simple-type-specifier
;
friend
typename-specifier
;
friend
Deklaracje
Jeśli zadeklarowano friend
funkcję, która nie została wcześniej zadeklarowana, ta funkcja zostanie wyeksportowana do otaczającego zakresu nieklasowego.
Funkcje zadeklarowane w friend
deklaracji są traktowane tak, jakby zostały zadeklarowane przy użyciu słowa kluczowego extern
. W celu uzyskania więcej informacji, zobacz następujący temat: extern
.
Mimo że funkcje z zakresem globalnym można zadeklarować jako friend
funkcje przed ich prototypami, funkcje składowe nie mogą być deklarowane jako friend
funkcje przed pojawieniem się ich pełnej deklaracji klasy. Poniższy kod pokazuje, jak taka deklaracja kończy się niepowodzeniem:
class ForwardDeclared; // Class name is known.
class HasFriends
{
friend int ForwardDeclared::IsAFriend(); // C2039 error expected
};
Powyższy przykład wprowadza nazwę ForwardDeclared
klasy do zakresu, ale kompletna deklaracja (w szczególności część, która deklaruje funkcję IsAFriend
) nie jest znana. deklaracja friend
w klasie HasFriends
generuje błąd.
W języku C++11 istnieją dwie formy deklaracji przyjaznych dla klasy:
friend class F;
friend F;
Pierwszy formularz wprowadza nową klasę F, jeśli żadna istniejąca klasa o tej nazwie nie została znaleziona w najbardziej wewnętrznej przestrzeni nazw. C++11: Drugi formularz nie wprowadza nowej klasy; może być używany, gdy klasa została już zadeklarowana i musi być używana podczas deklarowania parametru typu szablonu lub typedef
jako friend
.
Użyj friend class F
polecenia , gdy nie został jeszcze zadeklarowany przywołyny typ:
namespace NS
{
class M
{
friend class F; // Introduces F but doesn't define it
};
}
Błąd występuje, jeśli używasz friend
z typem klasy, który nie został zadeklarowany:
namespace NS
{
class M
{
friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
};
}
W poniższym przykładzie friend F
odwołuje się do F
klasy zadeklarowanej poza zakresem NS.
class F {};
namespace NS
{
class M
{
friend F; // OK
};
}
Użyj friend F
polecenia , aby zadeklarować parametr szablonu jako znajomy:
template <typename T>
class my_class
{
friend T;
//...
};
Użyj friend F
polecenia , aby zadeklarować typedef jako znajomego:
class Foo {};
typedef Foo F;
class G
{
friend F; // OK
friend class F // Error C2371 -- redefinition
};
Aby zadeklarować dwie klasy, które są przyjaciółmi siebie, cała druga klasa musi być określona jako przyjaciel pierwszej klasy. Przyczyną tego ograniczenia jest to, że kompilator ma wystarczającą ilość informacji, aby zadeklarować poszczególne funkcje znajome tylko w momencie deklarowania drugiej klasy.
Uwaga
Mimo że cała druga klasa musi być przyjacielem pierwszej klasy, możesz wybrać, które funkcje w pierwszej klasie będą przyjaciółmi drugiej klasy.
friend — funkcje
friend
Funkcja jest funkcją, która nie jest składową klasy, ale ma dostęp do prywatnych i chronionych składowych klasy. Funkcje przyjazne nie są uważane za składowe klasy; są normalnymi funkcjami zewnętrznymi, które mają specjalne uprawnienia dostępu. Znajomi nie należą do zakresu klasy i nie są wywoływani przy użyciu operatorów wyboru składowych (. i ->), chyba że są członkami innej klasy. friend
Funkcja jest zadeklarowana przez klasę, która udziela dostępu. Deklarację friend
można umieścić w dowolnym miejscu w deklaracji klasy. Nie ma to wpływu na słowa kluczowe kontroli dostępu.
W poniższym przykładzie przedstawiono klasę Point
i przyjazną funkcję ChangePrivate
. Funkcja friend
ma dostęp do prywatnego elementu członkowskiego Point
danych obiektu odbieranego jako parametr.
// 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
}
Członkowie klasy jako przyjaciele
Funkcje składowe klasy można zadeklarować jako znajomi w innych klasach. Rozważmy następujący przykład:
// 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
W poprzednim przykładzie tylko funkcja A::Func1( B& )
ma dostęp friend
do klasy B
. W związku z tym dostęp do prywatnego elementu członkowskiego _b
jest poprawny w Func1
klasie A
, ale nie w elemencie Func2
.
Klasa friend
jest klasą, której funkcje składowe są friend
funkcjami klasy, czyli, których funkcje składowe mają dostęp do prywatnych i chronionych składowych innej klasy. Załóżmy, friend
że deklaracja w klasie B
była:
friend class A;
W takim przypadku wszystkie funkcje składowe w klasie A
miałyby dostęp friend
do klasy B
. Poniższy kod jest przykładem friend
klasy:
// 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();
}
Przyjaźń nie jest wzajemna, chyba że zostanie jawnie określona. W powyższym przykładzie funkcje YourClass
składowe nie mogą uzyskiwać dostępu do prywatnych elementów członkowskich programu YourOtherClass
.
Typ zarządzany (w języku C++/CLI) nie może mieć żadnych friend
funkcji, friend
klas ani friend
interfejsów.
Przyjaźń nie jest dziedziczona, co oznacza, że klasy pochodzące z YourOtherClass
klasy nie mogą uzyskać dostępu do YourClass
prywatnych elementów członkowskich. Przyjaźń nie jest przechodnia, więc zajęcia, które są przyjaciółmi YourOtherClass
, nie mogą uzyskać dostępu do YourClass
prywatnych członków.
Na poniższej ilustracji przedstawiono cztery deklaracje klas: Base
, Derived
, aFriend
i anotherFriend
. Tylko klasa aFriend
ma bezpośredni dostęp do prywatnych elementów członkowskich Base
(i do wszystkich elementów członkowskich Base
mogły dziedziczyć).
Na diagramie pokazano, że klasa anotherFriend nie ma przyjaznej relacji z bazą klas, którą przyjaciele klasy aFriend. Klasa aFriend jest przyjazna dla klasy Base, ale nie ma relacji zaprzyjaźnionej z klasą Pochodne, mimo że klasa Pochodna dziedziczy z bazy. Pokazuje to, że dziedziczenie nie oznacza, że klasa pochodna ma tych samych przyjaciół co klasa bazowa.
Definicje wbudowane friend
Funkcje przyjazne można zdefiniować (biorąc pod uwagę treść funkcji) wewnątrz deklaracji klas. Te funkcje są funkcjami wbudowanymi. Podobnie jak w przypadku funkcji wbudowanych składowych, zachowują się tak, jakby były zdefiniowane natychmiast po wystąpieniu wszystkich składowych klasy, ale przed zamknięciem zakresu klasy (na końcu deklaracji klasy). Przyjazne funkcje zdefiniowane wewnątrz deklaracji klas znajdują się w zakresie otaczającej klasy.
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla