Was genau bewirkt das "using namespace std" in einem C++-Programm?
Es muss wohl etwas mit der Verwendung von bspw. "cin" und "cout" im Programm zu tun haben, aber sind diese Befehle nicht ohnehin in der "iostream"-Bibliothek enthalten, die man icludieren muss? I/O steht doch für Ein/Ausgabe
3 Antworten
Kurze Antwort:
Trotz des Include musst Du ohne "using..." schreiben:
std::cin
std::cout
Mit using kannst du darin std:: weglassen. Es ist aber kein guter Stil, "using namespace" auf Dateiebene (also am Anfang einer cpp-Datei) zu verwenden. Wenn, sollte es innerhalb der Methode stehen, die das benötigt. Für std ist das aber nie notwendig, es gibt aber andere Bibliotheken mit stark verschachtelten Namespaces (z.B. boost), da bietet sich das schon an.
Namespaces dienen der logischen Segmentierung, sodaß unter anderem auch Namenskolliisionen minimiert werden. Using namespace <name>; bricht diese Segmentierung auf, indem es den Namespace <name> in den globalen Namespace hinüberzieht.
Ich hoffe Du bist mir nicht böse, aber ein "Umzug" ist e eigentlich nicht.
Die Klausel ermöglicht, die Definitionen des angesprochenen Namespace im aktuellen Scope ohne die eigentlich erforderliche Namespace-Qualifizierung zu verwenden.
"using namespace" auf Quelldateiebene ist eigentlich bäh, erst recht in Headern. Ich halte die aber auf Methodenebene für sehr sinnvoll.
Man kann sich natürlich vortrefflich streiten, wie man es formal am besten beschreibt. Letzlich bricht man die Kapselung auf und zieht es in die aktuelle Scope (nicht zwingend globale Scope) da hast Du natürlich recht.
Das war auch eher aus der Frustration heraus, daß auch in Lehrmaterial häufig direkt unter den #include-s ein using namespace gemacht wird und das ist in den seltensten Fällen das, was man möchte. (Ich müßte jetzt allerdings selbst erst im Standard schauen, ob durch die 'translation unit' noch einmal gescoped wird, oder ob es dann wirklich direkt in :: landet.)
Wie dem auch sei, neben Methoden kann es auch in einer Unit sinnvoll sein, wenn ich zum Beispiel einen eigenen Namespace für meine Bibliothek habe und den std Namespace direkt reinziehen möchte, weil ich genau weiß, daß keine Kollisionen zu erwarten sind.
Naja, es sind ja nicht nur die Kollisionen. Auch ein späterer Leser des Codes hat es einfacher, wenn er "std::thread" vorfindet, statt einfach nur "thread".
Außerdem - bei einer neueren STL-Version müsstest Du Deinen Code überprüfen, ob deren neue Elemente mit Deinem alten Code kollidieren. Es gibt da lustige und schwer zu findende Fehler ;-)
Stimmt, ich votiere ohnehin dafür es lieber voll zu qualifizieren, wenn es nicht gerade (wie bei Deinem Beispiel mit Boost) so tiefe Namernraumshierachien sind, daß einem die Finger abbrechen.
Und dann eben im Idealfall auch so, daß man direkt sieht, was in welche Scope geholt wurde.
Ich finde es schade, dass es bei Namespaces nicht ebenso geht wie bei Typen:
using siTemperature = boost::units::si::temperature;
geht,
using namespace si = boost::units::si;
geht aber leider nicht. Dann wäre der Code besser lesbar, trotzdem ist die "fremde" Herkunft sofort erkennbar.
Sollte das nicht mit der Definition eines eigenen Namespace machbar sein?
namespace si{
using namespace boost::units::si;
}
si::<whatever>
Oder übersehe ich gerade etwas?
Und aus
using namespace si = boost::units::si;
Mache ein:
namespace si = boost::units::si;
Und schon hast Du ein Aliasing gemacht, sodaß Du über si:: innerhalb der Scope den vollqualifizierten Namespace ansprechen kannst ;-).
Ist eine Idee, muss ich bei nächster Gelegenheit ausprobieren - im Moment habe ich nach dem Qt 12.1 Installationsversuch gar keine C++ Umgebung.
Tatsächlich, es funktioniert beides. Die erste Variante finde ich eigentlich ein starkes Stück, aber ist egal, man muss ohnehin aufpassen, was man macht.
Letztlich liegt es eben an den schmutzigen Details der Namespaces, die im Endeffekt ein Lookupo-Tree sind (wenn Du es Dir vorstellen möchtest), die dann in verschiedenen Scopes gebunden werden.
Eventuell wird jetzt auch verständlicher, warum ich das salopp als 'umziehen' formuliert hatte.
Ich muß das in sofern korrigierend ergänzen, als daß ich natürlich auch in einen neuen Namespace (um)ziehen kann, es muß nicht immer der globale NS sein.
Allerdings ist das (leider) eine der häufigsten Verwendungen.