Un uso tipico è di concedere l'accesso a funzioni che fanno parte dell'interfaccia di classe, ma grazie ad altre regole non può davvero essere parte della classe corretta. Gli inseritori / estrattori per iostreams sono un esempio classico:
namespace whatever {
class something {
// ...
friend std::ostream &operator<<(std::ostream &os, something const &thing);
friend std::istream &operator>>(std::istream &is, something &thing);
};
}
Fare in modo che questi operatori membri della classe lavorino non . Un'operazione di I / O è simile a:
whatever::something thing;
std::cout << thing;
Per un operatore implementato come funzione membro, questo sarebbe risolto come:
std::cout.operator<<(thing);
I.e., la funzione dovrebbe essere un membro di std::cout
, non di something
. Dato che non vogliamo modificare costantemente std::ostream
, la nostra unica opzione ragionevole è di sovraccaricare l'operatore con una funzione libera invece di una funzione membro. Questo ci lascia due possibilità: o ignorare completamente l'incapsulamento e rendere pubblico tutto in classe, oppure mantenerlo privato, ma concedere l'accesso alle poche cose che ne hanno veramente bisogno.
Rendere un altro classe un amico è piuttosto meno comune. In questo caso, di solito stai creando qualcosa sull'ordine di un modulo o sottosistema - un insieme di classi che lavorano insieme e hanno un certo grado di accesso speciale tra loro che non è concesso al mondo in generale.