header regeln?



  • Hallo,

    so, da ich gestern mein Projektchen bissel kaputt gemacht habe indem ich mich verheddert habe mit meinen Headerndateien, wollt ich ma fragen ob es "richtilnien" gibt die man einhalten sollte?

    Ich mein gestern hab ich mir ne neue Klasse "Netzwerk" gemacht und wollte die halt in mein Spielchen packen, aber dann hab ich mich so vertan das nichtsmehr ging šŸ˜ƒ

    also Netzwerk hat Spieler aufgerufen, was wiederum Netzwerk aufgerufen hat usw.
    Jetzt ja, iregndwie hab ich grad mĆ¼he mit dem Problem aber ich denke es liegt einfach daran das ich nicht weis wie ich am inteligentesten include...

    So, gibt es irgendwie richtlinien? was man wie includen soll?

    Danke vielmals!



  • Forward declaration funktioniert auch fuer Typen.



  • Wie schon gesagt forward Deklarationen benutzen.

    Beispiel:

    //spieler.h
    #ifndef SPIELER_H
    #define SPIELER_H
    #include "netzwerk.h"
    class Spieler{
    	Netzwerk *n;
    };
    #endif
    
    //netzwerk.h
    #ifndef NETZWERK_H
    #define NETZWERK_H
    #include "spieler.h"
    class Netzwerk{
    	Spieler *p;
    };
    #endif
    

    Hier siehst du den Konflikt, ohne Netzwerk keinen Spieler und ohne Spieler kein Netzwerk, also kannst du beides nicht includen.
    Lƶsung:

    //spieler.h
    #ifndef SPIELER_H
    #define SPIELER_H
    class Spieler; //forward declaration
    #include "netzwerk.h"
    class Spieler{
    	Netzwerk *n;
    };
    #endif
    
    //netzwerk.h
    #ifndef NETZWERK_H
    #define NETZWERK_H
    class Netzwerk;
    #include "spieler.h"
    class Netzwerk{
    	Spieler *p;
    };
    #endif
    

    Wenn du jetzt spieler.h includest, dann deklariert er Spieler ohne Netzwerk zu kennen (die forward declaration), includet dann netzwerk.h, was funktioniert, da er Spieler schon kennt und deklariert dann spieler richtig.



  • nwp3 schrieb:

    Lƶsung:

    //spieler.h
    #ifndef SPIELER_H
    #define SPIELER_H
    class Spieler; //forward declaration
    #include "netzwerk.h"
    class Spieler{
    	Netzwerk *n;
    };
    #endif
    
    //netzwerk.h
    #ifndef NETZWERK_H
    #define NETZWERK_H
    class Netzwerk;
    #include "spieler.h"
    class Netzwerk{
    	Spieler *p;
    };
    #endif
    

    Ne so nicht.
    Die ganzen include weg, weil nur Pointer verwendet werden, da reichen forwards defs.



  • und verdreht hast du es auch noch.



  • Es ist ein Minimalbeispiel. NatĆ¼rlich kann man sich die Header komplett sparen und die Klassen einfach in die main schreiben.

    AuƟerdem habe ich das nicht verdreht. Das meintest du:

    //spieler.h
    #ifndef SPIELER_H
    #define SPIELER_H
    class Netzwerk; //forward declaration
    class Spieler{
        Netzwerk *n;
    };
    #endif
    

    Ja, das wĆ¼rde auch gehen. Aber schon das hier geht nicht mehr:

    //spieler.h
    #ifndef SPIELER_H
    #define SPIELER_H
    class Netzwerk; //forward declaration
    class Spieler{
        Netzwerk n;
    };
    #endif
    

    Und wenn wir uns vorstellen, dass es kein Minimalbeispiel mehr ist und es 20 Klassen gibt, dann muss er in 20 Headern 20 forward Deklarationen machen und darauf achten, dass die ohne Pointer zuletzt kommen. Wenn er einfach die eigene Klasse forward deklariert, dann braucht er nur eine Deklaration zu machen und die Reihenfolge ist egal.



  • nwp3 schrieb:

    Wenn er einfach die eigene Klasse forward deklariert, dann braucht er nur eine Deklaration zu machen und die Reihenfolge ist egal.

    Dann muss die eigene Klasse wissen, in welchen Headern sie verwendet wird. D.h. du hast die Information an zwei Orten statt an einem, musst sie bei einer Ƅnderung entsprechend mehrfach anpassen.

    nwp3 schrieb:

    Und wenn wir uns vorstellen, dass es kein Minimalbeispiel mehr ist und es 20 Klassen gibt, dann muss er in 20 Headern 20 forward Deklarationen machen und darauf achten, dass die ohne Pointer zuletzt kommen.

    DafĆ¼r sieht man gleich im Header, wovon die Klasse abhƤngt (durch den vollstƤndigen Typen oder nur durch den Namen). Wenn du tatsƤchlich so viele VorwƤrtsdeklarationen benƶtigst, ist auch ein Fwd-Header eine Mƶglichkeit.



  • Nexus schrieb:

    Dann muss die eigene Klasse wissen, in welchen Headern sie verwendet wird.

    Wieso? Sie deklariert sich selbst forward und includet was sie braucht, dafĆ¼r muss sie gar nichts wissen, das ist ja gerade das gute.



  • nwp3 schrieb:

    Nexus schrieb:

    Dann muss die eigene Klasse wissen, in welchen Headern sie verwendet wird.

    Wieso? Sie deklariert sich selbst forward und includet was sie braucht, dafĆ¼r muss sie gar nichts wissen, das ist ja gerade das gute.

    Wenn jetzt aber jetzt jemand anders die Klasse forward declaren mƶchte muss er das auch immer noch selbst machen.
    Das was du machst spart dir gerade mal ein wenig Tipparbeit bei den Klassen, die die diese eine selbst inkludieren muss.

    Im Ć¼brigen ist das, was du machst komplett gegen den Sinn von VorwƤrtsdeklarationen. Man mƶchte mit VD AbhƤngigkeiten (aka includes von Headern) verringern. Das auflƶsen von zyklische AbhƤngigkeiten (welche oft ein Hinweise auf schlechtes Design sind) sind da eher ein netter Nebeneffekt.



  • Vielen Dank, werd es spƤter mal testen!



  • nwp3 schrieb:

    Wieso? Sie deklariert sich selbst forward und includet was sie braucht, dafĆ¼r muss sie gar nichts wissen, das ist ja gerade das gute.

    Sie includet eben nicht nur was sie braucht, sondern alles was irgendwie mal im Header erwƤhnt wird. Und der Header der deinen Klassenheader einbindet (wahrscheinlich nach dem selben Muster und deshalb unnƶtigerweise), bindet damit indirekt ein, was dein Klassenheader einbindet. Und alles, was DEN header dann einbindet... Das sind dann include-Kaskaden, wo mal schnell drei- bis vierstellige Anzahl von Inlcudes in einer .cpp zustandekommen, und das nur fĆ¼r ne Handvoll Pointer.

    Deshalb die Regel: Alles, was du nur als Pointer, Referenzen, Funktionsparameter oder RĆ¼ckgabetypen benutzt, nur forwƤrts deklarieren und nur was du wirklich brauchst includen.

    nwp3 schrieb:

    Und wenn wir uns vorstellen, dass es kein Minimalbeispiel mehr ist und es 20 Klassen gibt, dann muss er in 20 Headern 20 forward Deklarationen machen und darauf achten, dass die ohne Pointer zuletzt kommen.

    Wenn er 20 Klassen hat und jede jeweils von den 19 anderen abhƤngig ist, hat er ganz andere Probleme als die Header...
    (Und falls es ausnahmsweise doch mal Sinn machen sollte gibt es precompiled Header fĆ¼r genau solche Probleme)


Log in to reply