Gegenseitige Referenz
-
fR4gg3R schrieb:
...Ihr meint ich sollte das besser nur mit Zeigern machen?
Die spannende Frage lautet: Was machen ?
Wie gesagt: Wenn 2 Objekte (selbe Klasse oder unterschiedliche Klasse spielt keine Rolle) einander "kennen", muss man sich über die Rahmenbedingungen in Klaren sein:
- Was sollen sie miteinander anfangen können ?
- Gehört das eine dem anderen ?
- Kommt eines ohne das andere aus oder braucht es das andere zwingend ?
- Wer erzeugt die Objekte ? (Der "Erzeuger" muß halt vorher da sein)
- .....Wenn Du einfach nur ein wenig mit rumspielen willst (was eine seeeehr schöne und auch lehrreiche Beschäftigung ist
), solltest Du es einfach mal probieren mit:class BinEinDu; class B; class A : public BinEinDu { B habeDich; B& braucheDich; B* kenneDich; ... };
Einfach mal ein paar Member-Funktionen von A schreiben, die mit den Teilen rumhantieren, sie zurückgeben, ...
Da sagt einem der Compiler eigentlich schon eine Menge, was geht und was nicht.
Und wenn Dir langweilig ist, streust Du noch ein paar consts ein (in die Deklaration der "...Dich"'s und/oder der Memberfunktionen.
Da kann man sich gut und gerne ein paar Tage bis Wochen beschäftigen mit.Gruß,
Simon2.
-
Danke für den Link, aber das war mir schon klar, dass das entweder eine Copyconstruction aus einem Temporary oder eine Construction unter eliminierung des Temporary sein muss (falsch ausgedrückt).
Was mir jedoch nicht klar war, war dass man auf diesem Wege das Temporary eliminieren UND auf den zu initialisierenden Bezeichner zugreifen kann. Wenn ich das richtig verstehe kann man die Zeile
A a = *new B("Fred", a);weder durch die direkte Initialisierung
A a( *new B("Fred", a) );noch durch die Copy-Initialisierung via Temporary
A temp( *new B("Fred", <nix da>) ); A a( temp );äquivalent darstellen. Ich dachte immer die Copy-Initialisierung ist zu mindestens einem dieser beiden äquivalent. Aber man lernt bekanntlich nie aus

-
Klassenbeziehungen, wie süüs

Na dann üb ich mal ein bisschen, mit "brauchDich", "habDichLieb" und soweiter

Danke

Greez

-
LordJaxom schrieb:
Danke für den Link, aber das war mir schon klar, dass das entweder eine Copyconstruction aus einem Temporary oder eine Construction unter eliminierung des Temporary sein muss (falsch ausgedrückt).
Was mir jedoch nicht klar war, war dass man auf diesem Wege das Temporary eliminieren UND auf den zu initialisierenden Bezeichner zugreifen kann. Wenn ich das richtig verstehe kann man die Zeile
A a = *new B("Fred", a);weder durch die direkte Initialisierung
A a( *new B("Fred", a) );noch durch die Copy-Initialisierung via Temporary
A temp( *new B("Fred", <nix da>) ); A a( temp );äquivalent darstellen. Ich dachte immer die Copy-Initialisierung ist zu mindestens einem dieser beiden äquivalent. Aber man lernt bekanntlich nie aus

kommt darauf an, was du mit äquivalent meinst. jedenfalls führt die direkte initialisierung zum selben ergebnis. unterschiede könnten sich nur ergeben, wenn bei copy-initialisierung ein temporary erzeugt wird und das irgendwelche seiteneffekte zur folge hat. du könntest ja auch
A a( A( *new B("Fred", a) ) );schreiben

-
MSVC++2005 sagt sowohl zu
A a( A( *new B("Fred", a) ) );als auch zu
A a( *new B("Fred", a) );MSVC++2005 schrieb:
error C2065: 'a' : undeclared identifier

Nur die Copy-Initialisierung per Zuweisung wird akzeptiert.
-
stimmt, ja. da war ich wohl selbst ein wenig konfus.
camper schrieb:
ein bezeichner gilt als deklariert unmittelbar nach dem letzten deklarator (insbesondere vor seinem initialisierer).
ist ja nur die halbe wahrheit. der initialisierer ist ja selbst ein deklarator und regel lautet
3.3.1/1 The point of declaration for a name is immediately after its complete declarator (clause
and before its
initializer (if any), except as noted below.(für die diskussion unwesentliche absätze mit ausnahmen folgen)
-
wie kann man sich nur seitenweise darüber unterhalten wie man ein so schlechtes design umsetzen kann..
-
Eine Referenz ist intern ein derefrenzierter Zeiger, A* a; A& = *a;
struct B; struct A { B* b; B& my_B; A(B* b); }; struct B { A* a; A& my_A; B(A* a); }; A::A(B* b) : b(b), my_B(*b){ if (b) b->a = this; } B::B(A* a) : a(a), my_A(*a){ if (a) a->b = this; } int main() { A h(0); //Null-Zeiger struct B existiert noch nicht B m(&h);//Referenz auf h wird gebildet //und h erhält eine Referenz auf m von m. }mfg
-
Helmut S. schrieb:
Eine Referenz ist intern ein derefrenzierter Zeiger, A* a; A& = *a;
struct B; struct A { B* b; B& my_B; A(B* b); }; struct B { A* a; A& my_A; B(A* a); }; A::A(B* b) : b(b), my_B(*b){ if (b) b->a = this; } B::B(A* a) : a(a), my_A(*a){ if (a) a->b = this; } int main() { A h(0); //Null-Zeiger struct B existiert noch nicht B m(&h);//Referenz auf h wird gebildet //und h erhält eine Referenz auf m von m. }mfg
undefiniertes verhalten.
-
camper schrieb:
...undefiniertes verhalten.
Und das ist noch optimistisch betrachtet - ich würde auf eine Speicherschutzverletzung tippen:
Helmut S. schrieb:
...
... A::A(B* b) : b(b), my_B(*b)... // Hier wird (mit u.a. Code) 0 dereferenziert int main() { A h(0); ...mfg
OK, bei der Initialisierung einer Referenz muß der Compiler vielleicht nicht unbedingt dereferenzieren, aber alternativ wird er eben den hinter der Referenz stehenden Pointer auf "0" setzen .... was dann beim ersten Zugriff auf die Referenz den entsprechenden Fehler gibt.
Gruß,
Simon2.