Header oder nicht Header?



  • Einfache Stil-Frage. Was sollte ich bevorzugen?

    // Einkaufswagen.h
    
    #include <map>
    
    namespace std
    {class string;}
    
    using namespace std;
    
    class Einkaufswagen
    {
    public:
    	map<string, int> inhalt;
    };
    
    // Einkaufswagen.h
    
    #include <map>
    #include <string>
    
    using namespace std;
    
    class Einkaufswagen
    {
    public:
    	map<string, int> inhalt;
    };
    

  • Mod

    Keines von beidem.

    #include <map>
    #include <string>
    
    class Einkaufswagen
    {
    public:
        std::map<std::string, int> inhalt;
    };
    


  • Das:
    Einkaufswagen.hpp

    #ifndef MEIN_TOLLER_EINKAUFSWAGEN_HPP
    #define MEIN_TOLLER_EINKAUFSWAGEN_HPP
    
    #include <map>
    #include <string>
    
    class Einkaufswagen
    {
      std::map<std::string, int> m_inhalt;
    public:
      // Memberfunktionen
    };
    
    #endif
    


  • Kann man nicht sogar noch include <string> weglassen?


  • Mod

    Gugelmoser schrieb:

    Kann man nicht sogar noch include <string> weglassen?

    😕 Und woher soll dann std::string bekannt sein?



  • Aus dem map-Header. Funktioniert sogar. Ist vllt. implementationsabhängig?!



  • Hi schrieb:

    Ist vllt. implementationsabhängig?!

    Vielleicht..



  • Hi schrieb:

    Aus dem map-Header. Funktioniert sogar. Ist vllt. implementationsabhängig?!

    Glaube ich nicht. Ich glaube eher, daß in der "main.cpp" vor der "Einkaufswagen.hpp" die <string> (oder <iostream>) inkludiert wurde.



  • volkard schrieb:

    Hi schrieb:

    Aus dem map-Header. Funktioniert sogar. Ist vllt. implementationsabhängig?!

    Glaube ich nicht. Ich glaube eher, daß in der "main.cpp" vor der "Einkaufswagen.hpp" die <string> inkludiert wurde.

    deine kristallkugel aus der reparatur zurueck ? :p



  • Das funzt aber bei mir (VS2010):

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


  • 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...


Log in to reply