Condividi tramite


friend (C++)

In alcune circostanze, è utile per una classe concedere l'accesso a livello di membro alle funzioni che non sono membri della classe o a tutti i membri di una classe separata. Queste funzioni e classi gratuite sono note come amici, contrassegnate dalla friend parola chiave . Solo l'implementatore della classe può dichiarare i rispettivi elementi friend. Una funzione o una classe non può dichiararsi come un amico di qualsiasi classe. In una definizione di classe usare la friend parola chiave e il nome di una funzione non membro o di un'altra classe per concedere l'accesso ai membri privati e protetti della classe. In una definizione di modello un parametro di tipo può essere dichiarato come .friend

Sintassi

friend-declaration:
friend function-declaration
friend function-definition
friendelaborated-type-specifier ;;
friend simple-type-specifier ;
friend typename-specifier ;

friend Dichiarazioni

Se si dichiara una friend funzione che non è stata dichiarata in precedenza, tale funzione viene esportata nell'ambito non classe che lo racchiude.

Le funzioni dichiarate in una friend dichiarazione vengono considerate come se fossero state dichiarate usando la extern parola chiave . Per ulteriori informazioni, vedere extern.

Anche se le funzioni con ambito globale possono essere dichiarate come friend funzioni prima dei prototipi, le funzioni membro non possono essere dichiarate come friend funzioni prima dell'aspetto della dichiarazione di classe completa. Il codice seguente mostra in che modo una dichiarazione di questo tipo ha esito negativo:

class ForwardDeclared;   // Class name is known.
class HasFriends
{
    friend int ForwardDeclared::IsAFriend();   // C2039 error expected
};

L'esempio precedente immette il nome ForwardDeclared della classe nell'ambito, ma la dichiarazione completa (in particolare, la parte che dichiara la funzione IsAFriend) non è nota. la friend dichiarazione nella classe HasFriends genera un errore.

In C++11 esistono due forme di dichiarazioni friend per una classe:

friend class F;
friend F;

Il primo modulo introduce una nuova classe F se non è stata trovata alcuna classe esistente con tale nome nello spazio dei nomi più interno. C++11: la seconda maschera non introduce una nuova classe. Può essere usata quando la classe è già stata dichiarata e deve essere usata quando si dichiara un parametro di tipo di modello o typedef come friend.

Usare friend class F quando il tipo a cui si fa riferimento non è ancora stato dichiarato:

namespace NS
{
    class M
    {
        friend class F;  // Introduces F but doesn't define it
    };
}

Si verifica un errore se si usa friend con un tipo di classe che non è stato dichiarato:

namespace NS
{
    class M
    {
        friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
    };
}

Nell'esempio seguente si friend F riferisce alla F classe dichiarata all'esterno dell'ambito di NS.

class F {};
namespace NS
{
    class M
    {
        friend F;  // OK
    };
}

Usare friend F per dichiarare un parametro di modello come friend:

template <typename T>
class my_class
{
    friend T;
    //...
};

Usare friend F per dichiarare un typedef come friend:

class Foo {};
typedef Foo F;

class G
{
    friend F; // OK
    friend class F // Error C2371 -- redefinition
};

Per dichiarare due classi che rappresentano elementi Friend l'uno dell'altro, la seconda classe per intero deve essere specificata come Friend della prima classe. Il motivo di questa restrizione è che il compilatore dispone di informazioni sufficienti per dichiarare le singole funzioni Friend solo nel punto in cui la seconda classe viene dichiarata.

Nota

Sebbene la seconda classe per intero debba essere Friend della prima classe, è possibile selezionare le funzioni nella prima classe che saranno Friend della seconda classe.

funzioni di tipo friend

Una friend funzione è una funzione che non è membro di una classe, ma ha accesso ai membri privati e protetti della classe. Le funzioni Friend non sono considerate membri della classe; sono normali funzioni esterne a cui vengono assegnati privilegi di accesso speciali. Gli amici non sono inclusi nell'ambito della classe e non vengono chiamati usando gli operatori di selezione dei membri (. e ->), a meno che non siano membri di un'altra classe. Una friend funzione viene dichiarata dalla classe che concede l'accesso. La friend dichiarazione può essere inserita in qualsiasi punto della dichiarazione di classe. Non è interessato dalle parole chiave di controllo di accesso.

Nell'esempio seguente viene illustrata una classe Point e una funzione friend ChangePrivate. La friend funzione ha accesso al membro dati privato dell'oggetto Point ricevuto come parametro.

// 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
}

Membri di classe come elementi friend

Le funzioni membro di classe possono essere dichiarate come friend in altre classi. Si consideri l'esempio seguente:

// 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

Nell'esempio precedente, solo alla funzione A::Func1( B& ) viene concesso friend l'accesso alla classe B. Pertanto, l'accesso al membro _b privato è corretto nella Func1 classe A ma non in Func2.

Una friend classe è una classe tutte le cui funzioni membro sono friend funzioni di una classe, ovvero le cui funzioni membro hanno accesso ai membri privati e protetti dell'altra classe. Si supponga che la dichiarazione friend nella classe B sia stata:

friend class A;

In tal caso, a tutte le funzioni membro della classe A sarebbe stato concesso friend l'accesso alla classe B. Il codice seguente è un esempio di una friend classe:

// 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();
}

L'amicizia non è reciproca a meno che non venga specificata in modo esplicito come tale. Nell'esempio precedente le funzioni membro di YourClass non possono accedere ai membri privati di YourOtherClass.

Un tipo gestito (in C++/CLI) non può avere funzioni friend , friend classi o friend interfacce.

L'amicizia non viene ereditata, ovvero le classi derivate da YourOtherClass non possono accedere ai YourClassmembri privati. L'amicizia non è transitiva, quindi le classi che sono amici di YourOtherClass non possono accedere ai YourClassmembri privati.

Nella figura seguente vengono illustrate quattro dichiarazioni di classe: Base, Derived, aFriend e anotherFriend. Solo la classe aFriend ha accesso diretto ai membri privati di Base (e a tutti i membri che Base possa aver ereditato).

Diagramma che mostra le implicazioni di derivazione di una relazione friend.

Il diagramma mostra che la classe anotherFriend non ha una relazione friend con la classe base che gli amici classe aFriend. Class aFriend è friended dalla classe Base, ma non ha una relazione friend con la classe Derivata anche se la classe Derivata eredita da Base. Ciò dimostra che l'ereditarietà non implica che la classe derivata abbia gli stessi amici della classe di base.

Definizioni inline friend

Le funzioni Friend possono essere definite (dato un corpo di funzione) all'interno delle dichiarazioni di classe. Queste funzioni sono funzioni inline. Come le funzioni inline dei membri, si comportano come se fossero state definite immediatamente dopo che tutti i membri della classe sono stati visualizzati, ma prima che l'ambito della classe venga chiuso (alla fine della dichiarazione di classe). Le funzioni Friend definite all'interno delle dichiarazioni di classe rientrano nell'ambito della classe contenitore.

Vedi anche

Parole chiave