Mutual dependence mit Layering



  • Hallo,

    ich Trottel habe eine Woche lang an einem Projekt gearbeitet, was ich ausschließlich in Notepad++ implementiert habe und habe dabei anscheinend einen wichtigen Faktor vergessen (testen konnte ich zwischendurch nicht). Und zwar habe ich gegenseitige Abhängigkeiten verbaut - juhu! (zum Teil auch mit Referenzen und so)

    typische Situation:

    class A
    {
    private:
        B _b;
    };
    
    // ...
    
    class B
    {
    private:
        A _a;
    };
    

    Das man das Problem so nicht lösen kann habe ich bereits herausgefunden... Ist meine einzige Möglichkeit nun wirklich, das pImpl-Pattern anzuwenden mit forward declaration? Gibt es da nichts schöneres?
    Ich dachte immer, dass ich mit "modernem" C++ keine Pointer mehr benötige. Oder bezieht sich das eher darauf, dass ich kein new mehr benötige?

    Wie würdet ihr das Problem umgehen? Gibt es schönere Lösungen?

    Gracias!



  • Ich würde etwas am Design ändern. Ehrlich gesagt hatte ich noch nie zwei Klassen die voneinander abhängig waren.



  • theliquidwave schrieb:

    Ist meine einzige Möglichkeit nun wirklich, das pImpl-Pattern anzuwenden mit forward declaration? Gibt es da nichts schöneres?

    Abstrakte Basisklasse (in Java auch als Interface bekannt) wäre eine Möglichkeit.

    Ich dachte immer, dass ich mit "modernem" C++ keine Pointer mehr benötige. Oder bezieht sich das eher darauf, dass ich kein new mehr benötige?

    Typischer Irrtum. In modernem C++ arbeitet man nicht mehr mit besitzenden rohen Pointern. Die altbekannten C-Pointer können in C und altem C++ verschiedene Semantik haben. C-Pointer als optionale, umbiegbare Referenzen sind auch in modernem C++ noch erlaubt und üblich.



  • FreakY<3Cpp schrieb:

    Ich würde etwas am Design ändern. Ehrlich gesagt hatte ich noch nie zwei Klassen die voneinander abhängig waren.

    das kann ich mir aber auch nicht vorstellen. damit schaffst du ja ein komplett lineares design

    wie setzt du zum beispiel das observer oder visitor pattern um?



  • FreakY<3Cpp schrieb:

    Ich würde etwas am Design ändern. Ehrlich gesagt hatte ich noch nie zwei Klassen die voneinander abhängig waren.

    Ist hier nicht zu vermeiden.

    @pumuckl: Wie muss ich mir dann vorstellen das Problem zu lösen?
    Wenn ich in der / den Klassen als Memberattribute nur Pointer habe (seien es auch Smart-Pointer), so bleibt mir doch gar nichts anderes übrig, als dass ich das Objekt im Konstruktor auf dem Heap erstelle... oder übersehe ich etwas?



  • Skym0sh0 schrieb:

    wie setzt du zum beispiel das observer oder visitor pattern um?

    Ich hab mich vielleicht ein wenig falsch ausgedrückt. Was ich meinte ist, dass bei mir noch nie zwei Klassen jeweils ein Objekt der anderen Klasse als Member hatten. Das Visitor Pattern habe ich auch schon implementiert.



  • ok, ein object auf die jeweils andere klasse, ist aus meiner sicht auch dringligst(dieses wort sieht falsch aus O_o) zu vermeiden, aber gegenseitige abhängigkeiten kommen öfters vor



  • Skym0sh0 schrieb:

    ok, ein object auf die jeweils andere klasse, ist aus meiner sicht auch dringligst(dieses wort sieht falsch aus O_o) zu vermeiden

    1. dringlichst.
    2. es ist nicht zu vermeiden, es geht schlichtweg nicht. Was soll der Compiler denken, der das sieht? "Ok, ich hab ein A. Darin ein B. Darin ein A. Darin ein B. Darin ein - ach du mich auch mal..."

    @theliquidwave: normalerweise besitzt das A ein B, das B hat aber nur Zugriff auf das A, besitzt es aber nicht. Ganz simpel mit forward deklarations sieht das dann so aus:

    class A;
    
    class B {
      A papa;
    };
    
    class A {
      B myBKind;
    };
    

    Etwas mehr Entkopplung erhält man durch Interfaces/abstrakte Klassen:

    class BNeedsThis //or something like this
    {
    public:
      virtual void bar() = 0;
    };
    
    class B
    {
      BNeedsThis& iNeedThis;
    public:
      B(BNeedsThis & whatINeed) : iNeedThis(whatINeed)
      {}
    
      void foo() {iNeedThis.bar();}
    };
    
    class A : public BNeedsThis
    {
      B myB;
    public:
      A() : myB(*this) {}
    
      virtual void bar() {std::cout << ":-)\n";}
    };
    

    BNeedsThis gehört in die gleiche Ebene wie B, damit hat B keinerlei Abhängikeit mehr von der Höheren Ebene von A.


Anmelden zum Antworten