using in der .cpp und .h?



  • Servus,

    ich hatte schon mehrfach das Problem, dass ich mit der Auflösung der using-Direktive nicht klargekommen bin. Beispiel:

    foo.h

    #ifndef _FOO_H_
    #define _FOO_H_
    
    class foo
    {
    public:
        void bar (string str) {}
    };
    
    #endif
    

    foo.cpp

    #include <string>
    
    using std::string;
    
    #include "foo.h"
    

    main.cpp

    #include <string>
    
    using std::string;
    
    #include "foo.h"
    

    So, der Compiler (VC++ 2005 Express) bemängelt bei mir:

    c:\foo.h(7) : error C2061: Syntaxfehler: Bezeichner 'string'

    Wenn ich den strin-include und die using-Direktive auch in die foo.h schreibe, geht alles klar. Kann aber wohl nicht mein Ernst sein, oder? Muss ich das machen, oder gibts ne elegante Möglichkeit?

    Danke für Antworten!



  • Hallo,

    in Header-Dateien sollte man wirklich auf using verzichten, das bringt sonst u.U. Namensraumkonflikte mit sich. Dein Beispiel muss demnach so aussehen:

    //foo.h
    //KEINE Unterstrich vor Bezeichnern, die werden normal vom Compiler benutzt, könnte Ärger geben. 
    #ifndef FOO_H
    #define FOO_H
    
    #include <string>
    
    class foo
    {
    public:
        void bar (std::string str) {}
    };
    
    #endif
    
    //foo.cpp
    #include "foo.h"
    
    using std::string;
    
    void foo::bar(string str) { }
    
    //main.cpp
    #include "foo.h"
    
    foo f;
    string s;
    f.bar(s);
    

    MfG

    GPC



  • Dir bleibt nur std::string im Header, bitte NIEMALS using in Headern verwenden.


  • Mod

    N00Bie schrieb:

    So, der Compiler (VC++ 2005 Express) bemängelt bei mir:

    c:\foo.h(7) : error C2061: Syntaxfehler: Bezeichner 'string'

    bei mir funktioniert das problemlos. der fehler ist nicht im geposteten code zu suchen. im übrigen handelt es sich hier um eine using-deklaration und nicht um eine using-direktive. letztere sollte auf namespace-ebene in headern auf jeden fall vermieden werden. gegen die verwendung von using an sich ist auch in headern nichts einzuwenden.



  • hmm, habs nach GPC umgestellt. Funktioniert jetzt.

    Vielen Dank!



  • camper schrieb:

    gegen die verwendung von using an sich ist auch in headern nichts einzuwenden.

    Was meinst du damit? 😕

    Jedes namespace-level using (egal ob Deklaration oder Direktive) ist in Headern problematisch (wobei using-Deklarationen meist noch problematischer als using-Direktiven sind, da using-Deklarationen auch noch eine Reihenfolgeabhängigkeit besitzen). Einzig class-level using-Deklaration sind in Headern unproblematisch.


  • Mod

    HumeSikkins schrieb:

    camper schrieb:

    gegen die verwendung von using an sich ist auch in headern nichts einzuwenden.

    Was meinst du damit? 😕

    Jedes namespace-level using (egal ob Deklaration oder Direktive) ist in Headern problematisch (wobei using-Deklarationen meist noch problematischer als using-Direktiven sind, da using-Deklarationen auch noch eine Reihenfolgeabhängigkeit besitzen). Einzig class-level using-Deklaration sind in Headern unproblematisch.

    was genau ist z.b. an einer deklaration

    using std::string;
    

    im globalen namensraum in einem header problematisch?



  • Es gibt durchaus die Möglichkeit, dass jemand den Namen string im globalen Namensraum in einer Implementierungsdatei verwenden möchte. Damit, dass du den Namen vorher einführst nimmst du ihm diese Möglichkeit und sorgst dafür, dass er komische Compilerfehler bekommt, die kaum direkt daraus hervorgehen, dass er deinen Header benutzt.
    usings im globalen Namensraum in Headern sind unschön, vor allem wenn es derartig allgemeine Namen sind wie string. Wenn das in einem Namespace liegt und dokumentiert ist, ist das etwas anderes.


  • Mod

    .filmor schrieb:

    Es gibt durchaus die Möglichkeit, dass jemand den Namen string im globalen Namensraum in einer Implementierungsdatei verwenden möchte. Damit, dass du den Namen vorher einführst nimmst du ihm diese Möglichkeit und sorgst dafür, dass er komische Compilerfehler bekommt, die kaum direkt daraus hervorgehen, dass er deinen Header benutzt.
    usings im globalen Namensraum in Headern sind unschön, vor allem wenn es derartig allgemeine Namen sind wie string. Wenn das in einem Namespace liegt und dokumentiert ist, ist das etwas anderes.

    das überzeugt nicht. es ist ja nicht so, dasss dieses using unbedingt nur der bequemlichkeit dienen muss (aus reiner bequemlichkeit benutze ich using eigentlich nur in funktionen). deine argumentation läuft darauf hinaus, dass man keinen naman in headern deklarieren sollte, weil derselbe name vielleicht noch woanders benutzt werden soll. alternativ könnte ich ja auch schreiben:

    typedef std::string string;
    

    der effekt ist absolut identisch zum using. im übrigen kenne ich auch die erklärung, wie sie in "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" gegeben wird. die bezieht sich aber auf funktionen - und ich stimme zu, dass hier vorsicht walten sollte. das kann aber kaum dazu dienen alle using deklarationen in headern als zu gefährlich zu erklären.

    edit: gerade weil string kein exotischer bezeichner ist, halte ich es problematisch, ihn für irgendetwas anderes als std::string einzusetzen.



  • camper schrieb:

    das überzeugt nicht. es ist ja nicht so, dasss dieses using unbedingt nur der bequemlichkeit dienen muss (aus reiner bequemlichkeit benutze ich using eigentlich nur in funktionen). deine argumentation läuft darauf hinaus, dass man keinen naman in headern deklarieren sollte, weil derselbe name vielleicht noch woanders benutzt werden soll.

    Nein. Es geht nur darum, dass man den globalen Namensraum nicht verschmutzen soll, der wird schließlich vielerorts verwendet. Dafür wurden Namespaces schließlich eingeführt. Wenn ein Bezeichner sinnvoll in einen Namensraum eingeführt wird ist das using sehr praktisch und eindeutiger als ein typedef (und es funktioniert auch bei Objekten), aber der globale Namensraum ist eigentlich nur der Implementierung vorbehalten. Klar, string sollte man vielleicht nicht unbedingt verwenden, aber denke mal an allgemeinere Sachen wie copy oder sort. Die könnten in einer Implementierung durchaus benutzt werden und es reicht eine ungünstige Typkonstellation und der Anwender bekommt die tollen STL-Fehlermeldungen um die Ohren geworfen, obwohl er deren Header nie explizit inkludiert hat.

    camper schrieb:

    im übrigen kenne ich auch die erklärung, wie sie in "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" gegeben wird.

    Und wie lautet die?



  • camper schrieb:

    im übrigen kenne ich auch die erklärung, wie sie in "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" gegeben wird. die bezieht sich aber auf funktionen

    Wie kommst du darauf, dass die sich nur auf Funktionen bezieht? Das Beispiel verwendet Funktionen, das heiß aber doch nicht, dass die Regel nur Funktionen gilt. Die Regel bezieht sich eindeutig auf alle Namespace-Level usings.


Anmelden zum Antworten