Funzioni friend
Una funzione è detta friend (letteralmente “amica”) di una classe, diversa di quella eventuale di appartenenza, se può accedere a tutti i suoi membri dichiarati private. La funzione può essere di qualsiasi tipo, cioè una normale funzione o una funzione membro di una classe.
La dichiarazione di una funzione friend è molto semplice: basta inserire il prototipo della funzione nella definizione della classe, preceduto dalla parola chiave “friend” (non importa se nella sezione protetta o pubblica).
Per capire al meglio quanto detto vediamo un esempio:
class myclass
{
int a, b;
public:
void set(int i, int j)
friend int prodotto(myclass enzo);
} ;
void myclass::set(int i, int j)
{
a = i;
b = j;
}
int prodotto (myclass enzo)
{
return (a*b);
}
main()
{
myclass A;
A.set(5,3);
cout<<prodotto(A); //il risultato è 15
}
La funzione prodotto, che non è membro di una classe, è dichiarata friend della classe myclass, e quindi può accedere direttamente ai membri privati a e b.
Osservazioni:
- siccome è esterna può accedere agli oggetti della classe solo se l'oggetto interessato le è trasmesso come argomento;
- siccome non è una funzione membro va richiamata senza utilizzare l’operatore ”.” (la funzione non deve essere qualificata dal nome dell’oggetto).
Se una stessa funzione è friend di due o più classi, il suo prototipo preceduto da friend va inserito nelle dichiarazioni di tutte le classi interessate. Sorge allora un problema, come si può vedere dal seguente esempio:
class A
{
…
friend int funz(A, B); //qui il compilatore non sa che B è una classe
};
class B
{
…
friend int funz(A, B);
};
Ci sono due possibili soluzioni per far sapere al sistema che B è una classe: o si pone in testa al gruppo di istruzioni la dichiarazione anticipata "class B", oppure si inserisce nel prototipo che potrebbe generare errore la parola-chiave "class", ovvero:
friend int funz(A, class B);
Classi friend
Allo stesso modo delle funzioni è possibile definire un’intera classe come friend di un’altra classe. In questo modo la classe friend e tutte le sue funzioni membro avranno accesso ai membri privati definiti all’interno dell’altra classe, ma non ne ereditano le caratteristiche.
Per capire al meglio quanto detto vediamo un esempio:
class A
{
…
friend class B;
};
In tal caso si dice che B è una classe friend annidata in A.
L'uso di funzioni e classi friend permette di aggirare il data hiding (vedi Information hiding) ogni volta che classi diverse devono interagire strettamente o condividere gli stessi dati, pur restando distinte.
Nella pratica, le classi friend vengono raramente impiegate. La loro presenza consente semplicemente di gestire alcune situazioni molto particolari.
C'è da dire infine che le relazioni di tipo friend non sono simmetriche (se A è friend di B non è detto che B sia friend di A), né transitive (se A è friend di B e B è friend di C, non è detto che A sia friend di C). In sostanza ogni relazione deve essere esplicitamente dichiarata.