In Bezug auf den globalen namespace in C++
In C++, sollten wir voranstellen Zeug in den globalen namespace mit ::
?
Beispielsweise bei der Verwendung von WinAPI, die in C, soll ich tun ::HANDLE
statt HANDLE
, und ::LoadLibrary
statt LoadLibrary
? Was bedeutet C++ dazu sagen? Ist es generell eine gute Idee, factoring in Themen wie Lesbarkeit und Wartbarkeit?
- Etwas allgemeiner: Ist es gute Praxis, overqualify Namen? E. g. wenn ich mich innerhalb
namespace foo { ... }
, sollte ich fühle mich sicher in der Annahme, dassget()
rufen meinefoo::get()
oder sollte ich schreibenfoo::get()
oder sogar::foo::get()
auf der sicheren Seite? Was sind die Kosten und nutzen, dies zu tun?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als Namensraum nicht existiert und in C, nicht verwenden ::HANDLE Zugriff auf HANDLE-Typ.
Mit dem voranstellen :: für den globalen namespace ist eine gute Idee, zur besseren Lesbarkeit, Sie wissen, die Art, die Sie zugreifen möchten, ist aus dem globalen namespace.
Außerdem, wenn Sie sind in einem geschachtelten namespace und erklären sich mit den eigenen Typ BEHANDELN (zum Beispiel), dann wird der compiler verwenden Sie dieses anstelle von windows.h einer!
Also, lieber immer mit :: vor dem Namen, wenn die in verschachtelten namespace.
Namen in C++ kann sein, qualifizierte und unqualifizierte. Es gibt unterschiedliche Regeln für qualifizierte und nicht qualifizierte name-lookup.
::HANDLE
ist ein Qualifizierter name, in der Erwägung, dassHANDLE
ist ein voller name. Betrachten Sie das folgende Beispiel:Ich denke, dass die desicion der Wahl
HANDLE
vs.::HANDLE
ist eine Frage der coding style. Natürlich, wie mein Beispiel schon sagt, es könnte Situationen geben, wo das qualifying ist Pflicht. So, könnte man genauso gut verwenden::
nur für den Fall, es sei denn, die syntax ist etwas eklig für Sie.Der wichtigste Punkt von Interesse ist, was die Unterschiede sind aus der Sicht des Compilers, wie es bereits gesagt wurde, wenn du die
::
dann sind Sie mit qualifizierten lookup, anstatt unqualifiziertes lookup.Den Vorteil der Verwendung von qualifizierten lookup ist, dass es in der Lage zu lokalisieren einem bestimmten symbol immer. Der Nachteil ist, dass es immer lokalisieren, die insbesondere symbol-D. H. es wird deaktivieren Argument Dependent Lookup. ADL ist eine große und nützliche Teil der Sprache, und durch die Qualifikation, die Sie effektiv deaktivieren Sie es, und das ist schlecht.
Berücksichtigen Sie, dass Sie hatte eine Funktion
f
im globalen namespace, die Sie Hinzugefügt, eine ArtT
innerhalb einer namespace -N
. Nicht berücksichtigen Sie, dass Sie hinzufügen möchten, die eine überlastung derf
das würde einenT
als argument. Nach der Schnittstelle Prinzip, Sie können hinzufügenf
zu denN
namespace, wief
ist tatsächlich eine operation durchgeführtT
, und es so gehört mit dem Typ. In diesem Fall, wenn Sie code, genannt, (berücksichtigen Sie, dass generische code)::f(obj)
auf ein Objekt unbekannten TypsU
wird der compiler nicht in der Lage zu Holen::N::f(obj)
wie eine mögliche überlastung der code ist ausdrücklich aufgefordert, für eine überlastung im globalen namespace.Mit unqualifiziertes lookup gibt Ihnen die Freiheit zu definieren, die Funktionen, aus denen Sie gehören, zusammen mit den Arten, die als Argumente verwendet. Es ist zwar nicht genau das gleiche, betrachten den Einsatz von
swap
, wenn Sie qualifizierenstd::swap
dann wird es nicht abholen der hand gerolltvoid swap( T&, T& )
in IhremN
namespace...Ich würde nur voll qualifizieren-IDS, wenn der compiler sonst nicht abholen das element ich will.
Es ist weitgehend eine Frage des Stils; es gibt keine Leistung oder Effizienz betrifft zu sprechen. Es ist eine gute Praxis, auf die großen Projekte und Vorhaben zusammengestellt werden, die auf vielen verschiedenen Plattformen, wie unter diesen Umständen Kollisionen zwischen globalen Namen und Namen in einem Namensraum sind eher auftreten.
Normalerweise müssen Sie nicht voranstellen müssen
::
für den globalen namespace. (Nur in wirklich seltenen Fällen). IMHO schadet es der Lesbarkeit, aber auf der anderen Seite ist es wahrscheinlich nicht brechen wird Ihr codeHabe ich alle meine code in einem namespace, und ich Neige dazu, lieber den C++ - Header über den C-Headern, so das nur die Symbole Links in der global namespace eher von der Windows-API. Ich vermeiden, ziehen Sie Symbole aus anderen Namensräumen in den aktuellen namespace (z.B.,, ich habe nie
using namespace std;
), statt dessen lieber zu qualifizieren Dinge explizit. Dies steht im Einklang mit Google C++ style guide.Habe ich daher bekommen in die Gewohnheit, qualifying WinAPI Funktionsaufrufe mit
::
für ein paar Gründe:Konsistenz. Für alles außerhalb des aktuellen namespace, ich spreche es explizit (z.B.
std::string
), also warum nicht finden Sie in der Windows-APIs, die explizit (z.B.::LoadLibraryW
)? Die Windows-APIs namespace ist den globalen namespace.Viel WinAPI-Funktionen benannt sind generisch (z.B.
DeleteObject
). Es sei denn, Sie sind sehr vertraut mit dem code, den Sie gerade Lesen, können Sie nicht wissen, obDeleteObject
ist ein Aufruf, etwas in den aktuellen namespace oder der Windows-API. Also, ich finde die::
verdeutlicht.Viele Windows-frameworks haben Methoden mit dem gleichen Namen wie das raw-Aufrufe. Zum Beispiel
ATL::CWindow
hat eineGetClientRect
Methode mit eine etwas andere Signatur als die WinAPI istGetClientRect
. In diesem Rahmen ist es üblich, für die eigene Klasse abgeleitet werdenATL::CWindow
, also in Ihrer Klasse Umsetzung, ist es normal, zu sagenGetClientRect
zum aufrufen der geerbten ATL Methode und::GetClientRect
wenn Sie müssen aufrufen, um die WinAPI-Funktion. Es ist nicht unbedingt notwendig, da der compiler die richtige zu finden, basierend auf der Signatur. Trotzdem finde ich, dass die Unterscheidung verdeutlicht für den Leser.(Ich weiß die Frage war nicht wirklich über die WinAPI, aber das Beispiel wurde in Bezug auf die WinAPI.)
Nicht, wenn Sie nicht über eine
LoadLibrary
Methode in Ihrer Klasse Sie nicht müssen Verwendung der globalen scope. In der Tat, Sie sollte nicht Verwendung globaler Tragweite, weil, wenn Sie später hinzufügenLoadLibrary
zu Ihrer Klasse Ihre Absichten ist wohl das überschreiben der Globale Funktion...