header richtig verbinden



  • hallo,

    ich habe gerade folgendes problem:

    eine klasse A hat ein objekt der klasse B.
    die klasse B hat einen pointer auf das "sie besitzende" objekt der klasse A.

    wie muss ich da die header verbinden?

    bisher sieht es etwa so aus:

    // A.h
    #include "B.h"
    class A
    {
    B b;
    };
    
    // B.h
    #include "A.h"
    class B
    {
    A* a;
    };
    

    In allen Headerfiles sind auch die "ausschlussdirektiven"
    #ifndef
    #define
    #endif

    Dennoch nimmt der Compiler das so nicht.
    vermutlich mag er das nicht so gekreuzt einbinden?
    wie muss ich das richtig machen?

    danke im voraus


  • Mod

    Du musst in einen der beiden Header eine Vorwärtsdeklaration machen. Entweder:

    // A.h
    class B;
    
    class A
    {
    B b;
    };
    
    // B.h
    #include "A.h"
    class B
    {
    A* a;
    };
    

    oder

    // A.h
    #include "B.h"
    class A
    {
    B b;
    };
    
    // B.h
    class A;
    
    class B
    {
    A* a;
    };
    

    edit: Oder meinetwegen auch in beiden.



  • Ich frage mich immer wieder, warum Klassen, die so eine gegenseitige Abhängigkeit haben, überhaupt auf mehrere Dateien aufgeteilt werden müssen. Das würde mir gar nicht in den Sinn kommen. Aber naja ...

    // A.h
    #include "B.h"
    class A
    {
    B b;
    };
    
    // B.h
    class A;
    class B
    {
    A* a;
    };
    


  • Geht so leider noch nicht.

    in A.h kommt - wenn ich A in B.h forward deklariere und umgekehrt nicht - der Fehler:
    "B does not name a type"

    Wenn ich in beiden Dateien jeweils die andere Klasse noch forward deklariere, kommt:
    "B has incomplete type"

    Das verstehe ich nicht...


  • Mod

    😕
    Versuchst du etwa die Headerdateien selbst zu compilieren?



  • SeppJ schrieb:

    😕
    Versuchst du etwa die Headerdateien selbst zu compilieren?

    Nein, das kommt daher, dass in class A der member "b" kein Pointer/Referenz ist 😉
    Da geht forward declaration nicht.



  • nein - nicht, dass ich wüsste jedenfalls...

    [quote = "Makefile"]
    SOURCEOBJ = \
    (OBJDIR)/a.o (OBJDIR)/a.o\ (OBJDIR)/b.o\

    SOURCEHFILES = \
    (SRCDIR)/a.h (SRCDIR)/a.h\ (SRCDIR)/b.h\
    [/quote]



  • l'abra d'or schrieb:

    SeppJ schrieb:

    😕
    Versuchst du etwa die Headerdateien selbst zu compilieren?

    Nein, das kommt daher, dass in class A der member "b" kein Pointer/Referenz ist 😉
    Da geht forward declaration nicht.

    D.h.?
    Doch lieber alles in eine Datei bzw. je eine Datei, einmal Header, einmal Source?
    Oder kann man derart verschachtelte Klassen irgendwie aufteilen?
    Der Code ist einfach sehr lang sonst...


  • Mod

    l'abra d'or schrieb:

    SeppJ schrieb:

    😕
    Versuchst du etwa die Headerdateien selbst zu compilieren?

    Nein, das kommt daher, dass in class A der member "b" kein Pointer/Referenz ist 😉
    Da geht forward declaration nicht.

    Ups, gar nicht gesehen, dass es in einem Fall kein Pointer ist. Sonst hat man bei Fragen dieser Art immer den Fall das beide Klassen einen gegenseitigen Zeiger haben.

    An den Thredersteller: Die Forwärtsdeklaration muss dann in die B.h.



  • headerfiles schrieb:

    l'abra d'or schrieb:

    SeppJ schrieb:

    😕
    Versuchst du etwa die Headerdateien selbst zu compilieren?

    Nein, das kommt daher, dass in class A der member "b" kein Pointer/Referenz ist 😉
    Da geht forward declaration nicht.

    D.h.?

    Das heißt du machst entweder einen Pointer/Referenz aus b, oder du verzichtest in A.h auf forward declaration von B und machst ein normales "include B.h". In B.h musst du dann allerdings A vorab deklarieren, da du sonst wieder dein ursprüngliches Problem hast.



  • Ich habe jetzt also:

    //A.h
    #include "B.h"
    class A
    {
    B b;
    };
    

    und:

    //B.h
    #include "A.h"
    
    class A; // forward declaration
    
    class B
    {
    A* a;
    };
    

    richtig?
    Dann bekomme ich:
    "A.h: : error: 'B' does not name a type"


  • Mod

    Nimm mal das include aus B.h raus.



  • Dann geht es, wenn ich im source von B, also B.cc
    statt
    #include "B.h"
    einfach
    #include "A.h"
    mache.
    Soll das so sein?


  • Mod

    😕
    Was machst du?

    Mach einfach:

    // A.h
    // Include-Guards schreibe ich mal explizit hin.
    #ifndef A_H
    #define A_H
    
    #include "B.h"  // Weil A ein B als Member hat
    class A
    {
    B b;
    }; 
    
    #endif
    
    // B.h
    #ifndef B_H
    #define B_H
    
    class A;  // Weil B ein A* als Member hat
    
    class B
    {
    A* a;
    }; 
    #endif
    

    Dann ist es völlig egal in welcher Reihenfolge du was wo einbindest.



  • headerfiles schrieb:

    Dann geht es, wenn ich im source von B, also B.cc
    statt
    #include "B.h"
    einfach
    #include "A.h"
    mache.
    Soll das so sein?

    Deine Header mit Include Guards versehen, und natürlich auch in B.cc ein B.h includen. Sich auf das Include von B.h in A.h zu verlassen wäre fahrlässig.



  • Aber auch ein #include "A.h" in B.cc?



  • headerfiles schrieb:

    Aber auch ein #include "A.h" in B.cc?

    Das hängt davon ab, was Du in B.cc machen willst -- also ob Du eine Definition von A brauchst oder nicht. "class A;" deklariert einen Klassentypen. Das heißt, der Compiler weiß dann, dass es so eine Klasse gibt. Der Typ A ist aber erstmal unvollständig. Dementsprechend kannst Du keine Objekte von A anlegen, oder sizeof(A) benutzen. Dafür brauchst Du eine Definition von A.

    BTW: Meinen ersten Beitrag (post #3) hast Du wohl übersehen, wie?



  • Ich wollte es so machen, weil
    - meine Files arg lang wurden
    - ich für meine Klasse (A) einge Menge Funktionalitäten bereit stellen musste, die ich gern gekapselt haben wollte
    - es für die (automatisch generierte) Dokumentation übersichtlicher ist

    Eigentlich mag ich es nicht mehrere Klassen mit derart engem Zusammenhang zu schreiben (auch weil ich da einfach keine Ahnung von habe, wie ich das dann aufteilen kann, wie man hier sieht 🙂 ), aber das Framework liess das (m.E.) nicht anders zu.



  • Ich verlinke bei solchen Fragen immer gerne hier rauf.

    Hoffe hilft dir auch noch ein wenig zum Verständnis.



  • Gut gemachter Artikel, danke 🙂

    Danke allen für die schnelle Hilfe!


Anmelden zum Antworten