Seite 1 von 1

Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 26.04.2013, 22:21
von kaiserludi
Moin.

Ich habe eine Klasse Bar, die Membervariablen einer Klasse Foo hält. Vereinfacht sieht das so aus:

Code: Alles auswählen

class Bar
{
	Foo mFoo;
};
Es handelt sich dabei ausdrücklich um ein Foo, nicht etwa eine Foo& oder einen Foo*.
Entsprechend muss Bar.h Foo .h inkludieren und kann nicht einfach Foo via class Foo; vorraus deklarieren.

Nun benötigt aber eine Funktion aus Bar friend Zugriff auf Foo, während ich ungern auch dem ganze Rest von bar friend Zugriff auf Foo geben möchte.
Dummerweise muss nun aber Foo.h natürlich Bar.h inkludieren, damit ich eine Memberfunktion von Bar als Friend in Foo Angeben kann, einfach nur class Bar; eicht nur, wenn ich die ganze Klasse als friend angeben will, nicht bei einzelnen Funktionen.

Wie löse ich diese zirkulare Abhängigkeit nun ab besten auf?

Die beste Lösung, auf die ich bisher gekommen bin, ist dieser Pattern (Wenn das wirklich die beste Lösung ist, dann ist darauf bestimmt schon wer vor mir gekommen. Kann mir wer sagen, obs für den pattern einen konkreten Namen gibt?):

Code: Alles auswählen

class Foo;
class Bar;

class FooBar
{
	static void friendOfFoo(void);
	friend class Foo;
	friend class Bar;
};

class Foo
{
	friend void FooBar::friendOfFoo(void);
};

class Bar
{
	friend void FooBar::friendOfFoo(void);
	void friendOfFoo(void);
	Foo mFoo;
};
Damit schwirrt mir nun aber eine extra Klasse da rum, die nichts anderem dient, als Unzulänglichkeiten der Sprache auszugleichen.
Bei so etwas fundamentalem und primitiven muss es doch auch einfacher gehen?

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 26.04.2013, 22:38
von TGGC
http://stackoverflow.com/questions/6310 ... -as-friend

Aber: Muss es wirklich eine friend Methode geben? Und musst du wirklich einen Datamember statt einer Referenz/Pointer machen? Solche physikalischen Abhaengigkeiten sind meist nicht so toll.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 26.04.2013, 22:39
von Artificial Mind
Ich weiß, das ist jetzt nicht besonders hilfreich, aber trotzdem:
Wenn du nur der einen Funktion friend access gewähren willst, dem Rest von Foo aber nicht, ist es dann nicht eh sinnvoller, diese Funktion als freie/externe Funktion zu machen und nicht innerhalb von Foo?
Mir fällt nämlich kein guter Grund ein, nur der einen Memberfunktion den Zugriff zu geben, aber nicht der ganzen Klasse.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 26.04.2013, 23:51
von kaiserludi
TGGC hat geschrieben:http://stackoverflow.com/questions/6310 ... -as-friend

Aber: Muss es wirklich eine friend Methode geben? Und musst du wirklich einen Datamember statt einer Referenz/Pointer machen? Solche physikalischen Abhaengigkeiten sind meist nicht so toll.
Die Friend Funktion ist eine Factory Method. Nur Bar soll neue Foos erstellen können (copy construction aus bestehenden Foo-Instanzen hingegen ist public), weswegen der Foo-Konsturktor private ist. Gleichzeitig braucht aber Bar keinen weiteren Zugriff Implementierungsdetails von Foo. Deswegen möchte ich nur der Factory Method und nicht auch dem Rest von Bar Friend-Zugriff auf Foo geben.
Bar hält einen Vector<Foo>. Der Grund dafür, dass es kein Vector<Foo&> oder Vector<Foo*> ist, ist, dass ich so die Foos ohne dynamische Allokation erstellen kann.

EDIT: Zu deinem Link: Ja, das würde auch funktionieren, aber dann kann ich ja auch gleich so vorgehen, wie im FooBar Beispielcode aus dem OP oder wo ist der Vorteil, wnen ich einen FooPrivateAccessKey habe? FooBar könnte ich FooFactory nennen, dann wäre das eigentlic hauch ziemlich klar.
Ich habe mich eher gefragt, obs nicht irgendwie möglich ist, ohne eine zusätzliche Klasse auszukommen, aber scheint wohl nicht der Fall zu sein.
Artificial Mind hat geschrieben: Mir fällt nämlich kein guter Grund ein, nur der einen Memberfunktion den Zugriff zu geben, aber nicht der ganzen Klasse.
Der Grund ist, dass so nur diese Klasse auf ihre private Memberfunktion zugreifen kann. Auf eine freie Funktion hätte dann wieder jeder Zugriff.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 27.04.2013, 17:19
von TGGC
kaiserludi hat geschrieben:Bar hält einen Vector<Foo>. Der Grund dafür, dass es kein Vector<Foo&> oder Vector<Foo*> ist, ist, dass ich so die Foos ohne dynamische Allokation erstellen kann.
Klar werden auch in einem Vector<Foo> der Speicher der Elemente dynamisch angelegt, zumindest einmal und dann immer wenn die Kapazitaet des vectors nicht mehr fuer den Inhalt reicht. Dann wird der Speicher aller bisherigen Elemente sogar nochmal komplett umkopiert. Wenns trotzdem so sein muss, benutze doch einfach einen std::vector<Foo>*. Damit bezahlst du nur eine zusaetzliche Allokation bei der Konstruktion von Bla + 4 Byte mehr Speicherverbrauch fuer die physikalische Entkopplung.

Eine andere Frage ist, warum dies Factoryfunktionalitaet ueberhaupt in Bar ist und nicht in Foo, denn so ist Foo ja nie mehr allein nutzbar.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 27.04.2013, 17:47
von kaiserludi
Das der Vektor intern doch wieder dynamisch allokiert, ist mir bewusst. Ich wollte bloß weitere zusätzliche dynamische Allokationen vermeiden. Bei nur einer zusätzlichen pro Bar wäre das aber schon weniger wild.

Die Factoryfunktionalität kann leider nicht in Foo sein, weil der ganze Sinn hinter der Fabrikmethode ist, dass man sowohl von Foo als auch von Bar erben und dann einfach die Fabrikmethode dahingehend überschreiben kann, keine Foos, sondern Instanzen von von Foo erbenden Klassen zu erzeugen. Wäre die Funktion nun in Foo, dann könnte man sie entweder erst nach der Konstruktion der Instanz aufrufen, dessen Klasse man über die Funktion bestimmen will, was entsprechend natürlich zu spät wäre, oder man könnte, wenn die Funktion static macht, die nicht mehr in erbenden Klassen überschreiben.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 27.04.2013, 19:09
von TGGC
kaiserludi hat geschrieben:Ich wollte bloß weitere zusätzliche dynamische Allokationen vermeiden. Bei nur einer zusätzlichen pro Bar wäre das aber schon weniger wild.
Wenn du Speicherprobleme hast, das du schon auf jede Allokation schauen musst, dann solltest du ehh einen globalen Pool von Foo haben, die sich alle Bar-Instanzen teilen.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 27.04.2013, 19:46
von Blue Cobold
Ich denke hier sollte man wieder die generelle Frage nach dem: "Was soll da überhaupt gebaut werden?" gestellt werden. Denn bisher klingen die Ideen und Anforderungen eher gruselig. Friend-Factories, zyklische Abhängigkeiten und was nicht alles.
Da ist doch eher ein arges Fehldesign im Gange. Mit einer Beschreibung dessen, was hier überhaupt modelliert werden soll, ließe sich sicher eine deutlich bessere und vor allem auch saubere Lösung finden.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 27.04.2013, 19:50
von Artificial Mind
Ich finde das klingt ein wenig nach Abstract Factory Pattern.

Re: Freundfunktionen && zirkuläre Abhängigkeiten

Verfasst: 29.04.2013, 17:24
von kimmi
Wobei die AbstractFactory aber eine eigene Klasse spendiert werden sollte. Ansonsten fängt man sich nämlich all diesen Ärger mit den zyklischen Anhängigkeiten und dem daraus resultierenden Ärger ein.

Gruß Kimmi