En friend
hat eine Reihe von guten Verwendungsmöglichkeiten. Hier sind die beiden für mich unmittelbar sichtbaren Verwendungen:
Freund Definition
Die Friend-Definition erlaubt es, eine Funktion im Klassenbereich zu definieren, aber die Funktion wird nicht als Member-Funktion, sondern als freie Funktion des umschließenden Namespaces definiert und ist normalerweise nicht sichtbar, außer für argumentabhängige Lookups. Das macht es besonders nützlich für das Überladen von Operatoren:
namespace utils {
class f {
private:
typedef int int_type;
int_type value;
public:
// let's assume it doesn't only need .value, but some
// internal stuff.
friend f operator+(f const& a, f const& b) {
// name resolution finds names in class-scope.
// int_type is visible here.
return f(a.value + b.value);
}
int getValue() const { return value; }
};
}
int main() {
utils::f a, b;
std::cout << (a + b).getValue(); // valid
}
Private CRTP-Basisklasse
Manchmal ist es erforderlich, dass eine Richtlinie Zugriff auf die abgeleitete Klasse benötigt:
// possible policy used for flexible-class.
template<typename Derived>
struct Policy {
void doSomething() {
// casting this to Derived* requires us to see that we are a
// base-class of Derived.
some_type const& t = static_cast<Derived*>(this)->getSomething();
}
};
// note, derived privately
template<template<typename> class SomePolicy>
struct FlexibleClass : private SomePolicy<FlexibleClass> {
// we derive privately, so the base-class wouldn't notice that,
// (even though it's the base itself!), so we need a friend declaration
// to make the base a friend of us.
friend class SomePolicy<FlexibleClass>;
void doStuff() {
// calls doSomething of the policy
this->doSomething();
}
// will return useful information
some_type getSomething();
};
Ein ungekünsteltes Beispiel dafür finden Sie in diese Antwort. Ein anderer Code, der das verwendet, ist in diese Antwort. Die CRTP-Basis überträgt diesen Zeiger, um auf Datenfelder der abgeleiteten Klasse mit Hilfe von Data-Member-Zeigern zugreifen zu können.