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
friendelaborated-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 YourClassprywatnych elementów członkowskich. Przyjaźń nie jest przechodnia, więc zajęcia, które są przyjaciółmi YourOtherClass , nie mogą uzyskać dostępu do YourClassprywatnych członków.

Na poniższej ilustracji przedstawiono cztery deklaracje klas: Base, Derived, aFriendi 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ć).

A diagram that shows the derivation implications of a friend relationship.

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ż

Słowa kluczowe