Eine typische Verwendung besteht darin, Zugriff auf Funktionen zu gewähren, die Teil der Klassenschnittstelle sind, aber dank anderer Regeln nicht wirklich Teil der eigentlichen Klasse sein können. Inserter / Extraktoren für iostreams sind ein klassisches Beispiel:
namespace whatever {
class something {
// ...
friend std::ostream &operator<<(std::ostream &os, something const &thing);
friend std::istream &operator>>(std::istream &is, something &thing);
};
}
Es funktioniert nicht, diese Operatoren zu Mitgliedern der Klasse zu machen. Eine E / A-Operation sieht ungefähr so aus:
whatever::something thing;
std::cout << thing;
Für einen Operator, der als Mitgliedsfunktion implementiert ist, wird dies wie folgt gelöst:
std::cout.operator<<(thing);
Das heißt, die Funktion müsste Mitglied von sein std::cout, nicht von something. Da wir nicht std::ostreamständig Änderungen vornehmen möchten , besteht unsere einzig sinnvolle Option darin, den Operator mit einer freien Funktion anstelle einer Mitgliedsfunktion zu überladen. Das lässt uns zwei Möglichkeiten: entweder die Kapselung vollständig ignorieren und alles in der Klasse öffentlich machen oder es privat halten, aber Zugriff auf die wenigen Dinge gewähren, die es wirklich brauchen.
Eine andere Klasse zu einem Freund zu machen, ist eher selten. In diesem Fall erstellen Sie normalerweise etwas in der Größenordnung eines Moduls oder Subsystems - eine Reihe von Klassen, die zusammenarbeiten und einen gewissen besonderen Zugriff aufeinander haben, der der Welt insgesamt nicht gewährt wird.