Header oder nicht Header?



  • Pech gehabt.



  • Hi schrieb:

    Das funzt aber bei mir (VS2010):

    Betone bitte dabe immer das "bei mir". Garantiert ist dies jedenfalls nicht.

    Wurstinator schrieb:

    Einfache Stil-Frage. Was sollte ich bevorzugen?

    Mir fehlen bei den Anworten immer noch Erklärungen, die liefere ich jetzt kurz nach:

    1. Verwende niemals "using namespace" in Dateien die von anderen includiert werden (In der Regel sollte sich dies alleine auf Header beziehen). Der Grund ist das du ansonsten den Namensraum global ausleerst und damit den Sinn von Namensräumen zerstörst.

    2. Vorwärtsdeklarationen funktionieren ausschließlich mit Referenzen und Zeigern, sofern auf diese noch nicht in der Datei zugegriffen wird (zumal du noch das Problem hättest, das "class string;" als Vorwärtsdeklaration auch mit reinen Referenzen in der Schnittstelle nicht funktionieren würde, es ist eine Templateklasse mit Templateparametern).



  • Hi schrieb:

    Das funzt aber bei mir (VS2010):

    #include <map>
    
    int main()
    {
        std::map<std::string, int> m;
    }
    

    Irrelevant. Der C++ ISO Standard garantiert nicht, dass Dein Programm kompilierbar ist.



  • asc schrieb:

    2. Vorwärtsdeklarationen funktionieren ausschließlich mit Referenzen und Zeigern, sofern auf diese noch nicht in der Datei zugegriffen wird

    Und mit Funktionsrückgabetypen und -argumenten in Funktionsdeklarationen sowie mit templates, soweit in der Datei nicht (explizit oder implizit) auf Funktionen des Templates zugegriffen wird, die eine Definition der Klasse benötigen.



  • namespace std
    {class string;}
    

    da sollte eigentlich kaum nen compiler mitspielen oder ...
    std::string ist nen typedef auf std::basic_string<char> und keine eigenständige klasse.

    wenn <map> schon einbindest, und die eh <string> ebenfalls incudiert, dann machts eh kein unnerschied das <string> selber noch mal includierst. Im Gegenteil es ist sicher fuer STL-Impls, und funktioniert auch wo <map> nicht <string> includiert.

    Wenn da dranrumschrauben willst dann bitte so das <map> und <string> rausbekommst.
    Aber nen std::basic_string und ne std::map forwarden ist ned lustig 🙂 besser ne eigene klasse die nur map und string verwendet, und diese Pimpl'n (SIehe PIMPL Idom).

    Ciao ...



  • Es ging mir nur um die Unterschiede zwischen den Codes.

    Wie sieht es aus, wenn es sich nicht um Templates handelt?

    // Einkaufswagen.h
    class Supermarkt_Ware;
    
    class Einkaufswagen
    {
    public:
        Einkaufswagen() {}
        Supermarkt_Ware& ware_im_wagen(int index);
      // ...
    };
    
    // Einkaufswagen.cpp
    #include <einkaufswagen.h>
    #include <supermarkt_ware.h>
    
    Supermarkt_Ware& Einkaufswagen::ware_im_wagen(int index)
    {
     // ...
    }
    

    Oder sollte ich "supermarkt_ware.h" lieber im Einkaufswagen-Header inkludieren?



  • Wurstinator schrieb:

    Oder sollte ich "supermarkt_ware.h" lieber im Einkaufswagen-Header inkludieren?

    Gegenfrage: musst du ihn includieren?

    Siehe auch hier: http://gotw.ca/gotw/007.htm



  • So, wie der Code jetzt da steht, nicht, darum frage ich ja 😉

    Mir wurde auch schon gesagt, man sollte immer alles in Header inkludieren wenn möglich.



  • Wurstinator schrieb:

    Mir wurde auch schon gesagt, man sollte immer alles in Header inkludieren wenn möglich.

    Dann zeig demjenigen mal einen gehörigen Vogel. Je weniger includes du in einem Header hast, desto besser. Wenn eine forward declaration reicht, dann nimm die. Binde den Header in der .cpp ein. Sonst kriegst du unnötige Abhängigkeiten in deinen Code, siehe der Link den ich oben gepostet hab.



  • pumuckl schrieb:

    Wurstinator schrieb:

    Mir wurde auch schon gesagt, man sollte immer alles in Header inkludieren wenn möglich.

    Dann zeig demjenigen mal einen gehörigen Vogel. Je weniger includes du in einem Header hast, desto besser. Wenn eine forward declaration reicht, dann nimm die. Binde den Header in der .cpp ein. Sonst kriegst du unnötige Abhängigkeiten in deinen Code, siehe der Link den ich oben gepostet hab.

    Ich nehme forward-Deklarationen nur, um zyklische Abhängigkeiten zu vermeiden. Ansonsten werden alle benötigten Typen immer inkludiert. Aber auch nicht mehr.

    Außer, um so schwere Brocken wie die <windows.h> loszuwerden, gegen die wende ich schonmal Tricks an.



  • volkard schrieb:

    Ich nehme forward-Deklarationen nur, um zyklische Abhängigkeiten zu vermeiden. Ansonsten werden alle benötigten Typen immer inkludiert. Aber auch nicht mehr.

    So hab ichs früher auch gemacht. Bis ich in einem unserer Module in der Firma mal durch einen simplen Header mit Forward-Deklarationen die Buildzeit um 60% reduziert hab. Ab einem bestimmten Punkt lohnt sich das dann eben doch merklich...



  • pumuckl schrieb:

    volkard schrieb:

    Ich nehme forward-Deklarationen nur, um zyklische Abhängigkeiten zu vermeiden. Ansonsten werden alle benötigten Typen immer inkludiert. Aber auch nicht mehr.

    So hab ichs früher auch gemacht. Bis ich in einem unserer Module in der Firma mal durch einen simplen Header mit Forward-Deklarationen die Buildzeit um 60% reduziert hab. Ab einem bestimmten Punkt lohnt sich das dann eben doch merklich...

    Dann lag das eigentliche Problem aber woanders. Wie im <map> von msvc, der <stdexept> inkludiert, der wiederum <string> braucht. WObei msvc das wieder recht gut mit precompiled headers bekämpfen kann.
    Aufräumen hat bei mir aber immer *viel* mehr gebracht, als gelegentliches Pimpeln, Forwarden und Precompilen. Wenn Du natürlich dicke Oschis inkludieren mußt, die Du nicht beeinflussen kannst, dann trickse.



  • Wurstinator schrieb:

    Mir wurde auch schon gesagt, man sollte immer alles in Header inkludieren wenn möglich.

    Dann zeig demjenigen mal einen gehörigen Vogel. Je weniger includes du in einem Header hast, desto besser.

    Naja, er hat nicht ganz unrecht wenn man es nicht falsch versteht. Man sollte alle header inkludieren, die man braucht. Aber auch nicht mehr.

    Man soll halt nicht

    #include <map>
    

    schreiben, und das

    #include <string>
    

    weglassen weils halt beim verwendeten compiler geht - da dann lieber beides rein. Was man aber nicht braucht, included man wenns geht auch nicht.

    Auch bei einem eigenen Projekt sollte man sich meiner Meinung nach nicht darauf verlassen, das ein header b.h auch noch den header c.h mitbringt - das kann sich nämlich ändern.

    Konktret:
    b.h:

    #include "c.h"
    

    a.cpp:

    #include "b.h"
    #include "c.h" //selbst wenn es momentan unnötig ist! 
    //So muss ich mich nicht drum kümmern, das wenn ich denn header c.h in b.h nicht mehr brauche, ich plötzlich compilerfehler in a.cpp bekomme
    

Anmelden zum Antworten