Aggregation zwischen zwei Klassen



  • Hallo Zusammen,

    bin derzeit wieder ziemlich aktiv am Programmieren und mir ist da gerade was aufgefallen, dass ich leider in meinem Buch nicht erklärt bekomme. Es geht darum, dass beide Klassen gegenseitig eine Aggregation aufweisen und die Frage die sich mir stellt ist:

    * wieso muss man vor jeder Klassendeklaration in der Header, die andere Klassendeklaration stehen. Es wird iwas mit dem Kompiler zu tun haben. Beispiel:

    Klasse A:

    #ifndef A_H
    #define A_H
    
    #include "B.h"
    
    class B; <<<<<< Warum
    
    class A
    {
        .
        .
        .
    };
    
    #endif
    

    Klasse B:

    #ifndef B_H
    #define B_H
    
    #include "A.h"
    
    class A;  <<<<<< Warum
    
    class B
    {
        .
        .
        .
    };
    
    #endif
    

    Wenn ich die <<<<<< Warum Teile weglasse, funktioniert es nicht. Außer die Aggregation ist nur einseitig. Dachte, dass ich mithilfe der Header Datei die andere Klasse miteinbinde. Die Einbindung im Kompiler läuft dann wohl erst etwas später, da ich beim Kompilieren (ohne die <<<<<< Warum Teile), den Fehler einer undefinierte Referenz der Klasse B (in Klasse A) und vice versa bekomme.



  • Spiel mal Präprozessor und verrate uns, wie deiner Meinung nach A.h aussehen sollte, nachdem alle #include's behandelt wurden.



  • Das war sehr gut 👍
    Etwas nachdenken und es hat klick gemacht. Liegt auf der Hand. Wenn ich A.h einbinde, dann brauch ich vorab erstmal die Klasse B in A.h und vice versa, da ja in A.h die Klasse A die Klasse B benötigt. Wenn ich diese Deklaration zuvor nicht mache, dann hat die Klasse A ein Problem 🙂



  • Ich denke man versteht das ganz gut, wenn man schrittweise durchgeht, was Compiler und Preprocessor hier machen.
    Angenommen, du bindest in einer cpp-Datei "A.h" ein, weil du die Klasse A dort verwenden möchtest:

    MeinProgramm.cpp:

    #include "A.h" 
    int main()
    {
       A a;
    }
    

    Ein #include ist quasi wie ein "Copy&Paste" der eingebundenen Datei an der include-Position:

    MeinProgramm.cpp-preprocessed:

    #ifndef A_H
    #define A_H
    
    #include "B.h"
    ...
    

    Hier wird jetzt "B.h" eingebunden, also:

    MeinProgramm.cpp-preprocessed:

    #ifndef A_H
    #define A_H
    
    #ifndef B_H
    #define B_H
    
    #include "A.h"
    ...
    

    Und nochmal "A.h" ...

    MeinProgramm.cpp-preprocessed:

    #ifndef A_H
    #define A_H
    
    #ifndef B_H
    #define B_H
    
    #ifndef A_H
    // Hier kommt jetzt nichts, weil A.h schonmal eingebunden wurde und der Include-Guard (Zeile 2) greift.
    #endif
    
    // Hier kommt jetzt der rest von "B.h"
    class B
    {
       A* a;  // BÄM! A ist nicht definiert, weil die Include-Guards das verhindert haben.
    };
    
    ...
    

    Eine Lösung hierfür ist eben, eine Forward declaration von A zu machen. Das funktioniert allderings nur wenn du A nur derart verwendest, dass keine vollständige Definition von A notwendig ist (also z.B. als Pointer).

    Gruss,
    Finnegan



  • Tolle Antwort 👍 🙂 ,
    das verdeutlicht das alles nochmals sehr gut. In meinem Programm hab ich nur einen Pointer auf die Klasse, also benötige ich nicht die ganze Deklaration. Wenn ich richtiges Objekt A in B definieren würde, dann müsste alles deklariert sein, damit der Compiler weiß wie viel Speicherplatz er anfordern müsste, oder?

    Danke nochmals für die Antwort(en).


  • Mod

    Shor-ty schrieb:

    Wenn ich richtiges Objekt A in B definieren würde, dann müsste alles deklariert sein, damit der Compiler weiß wie viel Speicherplatz er anfordern müsste, oder?

    So ist es.



  • Noch als Ergänzung: Du kannst zwar kein richtiges Objekt A definieren aber du könntest Funktionen deklarieren, welche ein richtiges Objekt A zurückgeben oder als Parameter haben. Die Definition der Funktion muss dann aber an einer späteren Stelle, bei der die A Klasse dann auch definiert ist, folgen.


Log in to reply