Dies hat ein Huhn und Ei-Problem. Beide B
müssen vollständig für A
definiert werden, um B::Itemfunction
zu sehen.
class A
{
friend void B::Itemfunction(); <-- Itemfunction does not exist yet
private:
int number;
int size;
public:
int Randomfunction();
};
class B: public A
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
den Auftrag Swapping nicht entweder weil B
Bedürfnisse A
zu definierende Arbeit von A
zu erben.
class B: public A <-- A does not exist yet
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
class A
{
friend void B::Itemfunction();
private:
int number;
int size;
public:
int Randomfunction();
};
Lösung 1 nach vorne class B
definieren, so weiß der Compiler, dass B existiert, auch wenn es nichts davon weiß, und dann friend
die ganze Klasse, weil A
nur weiß B
existiert. OPs friend
Beziehung wird beibehalten.
class B; <-- forward definition of B
class A
{
friend class B; <-- friending all of B, not just the function
private:
int number;
int size;
public:
int Randomfunction();
};
class B: public A
{
private:
std::string Random;
public:
void Itemfunction();
void CheckLog();
};
ABER! Alle B
haben jetzt vollständigen Zugriff auf alle A
. Wenn A
möchte size
oder andere Mitglieder versteckt und unter seiner Kontrolle, hart zu halten. B
kann alle Funktionen von A
aufrufen und alle Mitgliedsvariablen von A
ändern. B
kann vollständig A
gestochen werden.
Dies skaliert auch nicht zu anderen Unterklassen.B
kann alle A
sehen, aber C
und können nicht.
Also sagen Sie, Sie haben ein weniger triviales Beispiel, wo A
niemandem erlauben kann, mit dem Wert size
zu verwirren. Vielleicht ist es die Kapazität eines internen Arrays, und wenn Sie size
ändern, wird A
über das Ende des zugewiesenen Speichers hinaus ausgeführt. Der Grund spielt hier keine Rolle; Für dieses Beispiel darf niemand außer A
size
ändern.
Dies führt uns zu Lösung 2: protected access und Accessor-Funktionen.
class A
{
protected: <-- all inheritors can access members in this block. No one else can
int number;
private: <-- only A can access members in this block
int size;
public:
int Randomfunction();
int getSize() <-- accessor function to provide read-only access to size
{
return size;
}
};
class B: public A
{
private:
std::string Random;
public:
void Itemfunction(); <-- can do anything to number and read size
void CheckLog(); <-- so can this
};
class C: public A
{
private:
std::string member;
public:
void doStuff(); <-- and this
void DoOtherStuff(); <-- and this
};
B
und C
können A::number
zugreifen und A::getSize
verwenden können, um den Wert von size
zu sehen. number
kann durch B
und C
geändert werden, aber size
kann nicht. Wenn Sie sich Sorgen machen über die Kosten für den Aufruf einer Funktion zum Lesen size
, seien Sie nicht. Wenn der Compiler mit A::getSize
fertig ist, werden Sie nicht einmal wissen, dass es da ist. Es ist wahrscheinlich nicht.
Vielen Dank für die Antwort, ah ich sehe das Thema in Kreisen jetzt gehen. Ich denke, abgesehen von der Lösung, die Sie beschrieben haben, sollte Klasse B ein Freund von A auch richtig funktionieren? Oder würde es Probleme geben, eine abgeleitete Klasse und ein Freund zu sein? –
Denken Sie an die Bedürfnisse Ihres Programms. Wenn 'A' Freunde' B' so dass 'B' Zugriff hat, was dann von Kindern' C' oder 'D'? Die Freundschaft wird nicht skaliert, wenn Sie Unterklassen hinzufügen. [Geschützter Zugriff wird] (http://en.cppreference.com/w/cpp/language/access), wenn Sie das wollen. – user4581301
@ afc_1995 'protected' wurde entwickelt, um genau dieses Problem zu lösen, also sollten Sie' protected' wirklich verwenden. Wenn "B" mit "A" befreundet ist, kann es auf alles zugreifen, einschließlich privater Mitglieder. Der ganze Punkt, sowohl geschützt als auch privat zu sein, ist so, dass A entscheiden kann, wozu seine Kinder Zugang haben. Gibt es irgendeinen Grund, warum du Freundschaft lieber schützt? –