Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
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
friend
elaborated-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 YourClass
membri privati. L'amicizia non è transitiva, quindi le classi che sono amici di YourOtherClass
non possono accedere ai YourClass
membri 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).
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.