Ich habe diese Codezeile in einer Klasse gefunden, die ich ändern muss:
::Configuration * tmpCo = m_configurationDB;//pointer to current db
und ich weiß nicht genau, was der Doppelpunkt vor dem Klassennamen bedeutet. Ohne das würde ich lesen: Deklaration tmpCo
als Zeiger auf ein Objekt der Klasse Configuration
... aber der vorangestellte Doppelpunkt verwirrt mich.
Ich fand auch:
typedef ::config::set ConfigSet;
c++
syntax
namespaces
scope-resolution
global-namespace
rmbianchi
quelle
quelle
::
bezieht sich das nackte Mittel auf die Variable aus dem globalen / anonymen Namespace.Antworten:
Dadurch wird sichergestellt, dass die Auflösung über den globalen Namespace erfolgt, anstatt mit dem Namespace zu beginnen, in dem Sie sich gerade befinden. Wenn Sie beispielsweise zwei verschiedene Klassen
Configuration
als solche aufgerufen haben :Grundsätzlich können Sie bis zum globalen Namespace wechseln, da Ihr Name in diesem Fall möglicherweise durch eine neue Definition in einem anderen Namespace überlastet wird
MyApp
.quelle
::Configuration::doStuff(...)
::
beiden Begriffe zwischen dem Namespace oder der Klasse und ihrem Mitglied beziehen. Aber was ist mit dem ersten?Der
::
Operator wird als Scope-Resolution-Operator bezeichnet und löst genau das, er löst den Scope auf. Wenn Sie diesem Typnamen einen Präfix voranstellen, wird Ihr Compiler angewiesen, im globalen Namespace nach dem Typ zu suchen.Beispiel:
quelle
Viele vernünftige Antworten schon. Ich werde mich mit einer Analogie befassen, die einigen Lesern helfen kann.
::
funktioniert ähnlich wie das Dateisystem-Verzeichnis-Trennzeichen '/
', wenn Sie Ihren Pfad nach einem Programm durchsuchen, das Sie ausführen möchten. Erwägen:Dies ist sehr explizit - nur eine ausführbare Datei an genau dieser Stelle im Dateisystembaum kann mit dieser Spezifikation übereinstimmen, unabhängig vom gültigen PATH. Ähnlich...
... ist im C ++ - Namespace "tree" gleichermaßen explizit.
Im Gegensatz zu solchen absoluten Pfaden können Sie gute UNIX-Shells (z. B. zsh ) konfigurieren , um relative Pfade unter Ihrem aktuellen Verzeichnis oder einem beliebigen Element in Ihrer
PATH
Umgebungsvariablen aufzulösen. Wenn alsoPATH=/usr/bin:/usr/local/bin
und Sie "in" waren/tmp
, dann ...... würde gerne rennen,
/tmp/X11/xterm
wenn gefunden, sonst/usr/bin/X11/xterm
, sonst/usr/local/bin/X11/xterm
. Angenommen, Sie befanden sich in einem Namespace namensX
und hatten ein "using namespace Y
" in Kraft, dann ...... könnte in einem gefunden werden
::X::std::cout
,::std::cout
,::Y::std::cout
und möglicherweise an anderen Orten aufgrund Argument abhängiger Lookup (ADL, auch bekannt als Koenig - Lookup). Es ist also nur::std::cout
wirklich explizit, welches Objekt Sie genau meinen, aber zum Glück würde niemand, der bei klarem Verstand ist, jemals eine eigene Klasse / Struktur oder einen eigenen Namespace mit dem Namen "std
" oder etwas mit dem Namen "cout
" erstellen. In der Praxisstd::cout
ist es also in Ordnung , nur zu verwenden .Bemerkenswerte Unterschiede :
1) Shells verwenden in der Regel die erste Übereinstimmung mit der Reihenfolge in
PATH
, während C ++ einen Compilerfehler ausgibt, wenn Sie mehrdeutig waren.2) In C ++ Namen ohne führende Bereich kann in den aktuellen Namensraum angepasst werden, während die meisten UNIX - Shells nur das tun , wenn Sie setzen
.
in derPATH
.3) C ++ durchsucht immer den globalen Namespace (wie
/
implizit IhrenPATH
).Allgemeine Diskussion über Namespaces und Explizite von Symbolen
Die Verwendung absoluter
::abc::def::...
"Pfade" kann manchmal nützlich sein, um Sie von anderen Namespaces zu isolieren, die Sie verwenden, die Teil des Inhalts oder sogar anderer Bibliotheken sind, die der Clientcode Ihrer Bibliothek ebenfalls verwendet, aber nicht wirklich kontrolliert. Andererseits werden Sie auch enger an die vorhandene "absolute" Position des Symbols gekoppelt, und Sie vermissen die Vorteile des impliziten Abgleichs in Namespaces: weniger Kopplung, einfachere Mobilität des Codes zwischen Namespaces und präziserer, lesbarer Quellcode .Wie bei vielen Dingen ist es ein Balanceakt. Die C ++ Standard - Puts vielen Kennungen unter ,
std::
dass weniger „einzigartig“ alscout
, dass Programmierer für etwas ganz anderes in ihrem Code verwenden kann (zBmerge
,includes
,fill
,generate
,exchange
,queue
,toupper
,max
). Zwei nicht verwandte Nicht-Standard-Bibliotheken haben eine weitaus höhere Wahrscheinlichkeit, dieselben Bezeichner zu verwenden, da sich die Autoren im Allgemeinen nicht oder weniger bewusst sind. Und Bibliotheken - einschließlich der C ++ Standard-Bibliothek - ändern ihre Symbole im Laufe der Zeit. All dies führt möglicherweise zu Mehrdeutigkeiten beim Neukompilieren von altem Code, insbesondere wennusing namespace
s häufig verwendet wird: Das Schlimmste, was Sie in diesem Bereich tun können, ist Zulassenusing namespace
s in Headern, um den Gültigkeitsbereichen der Header zu entgehen, sodass eine beliebig große Menge direkten und indirekten Client-Codes nicht in der Lage ist, selbst zu entscheiden, welche Namespaces verwendet werden sollen und wie Mehrdeutigkeiten verwaltet werden sollen.Ein Leading
::
ist also ein Werkzeug in der Toolbox des C ++ - Programmierers, um einen bekannten Konflikt aktiv zu disambiguieren und / oder die Möglichkeit zukünftiger Mehrdeutigkeiten auszuschließen.quelle
::
ist der Operator für die Bereichsauflösung. Es wird verwendet, um den Umfang von etwas anzugeben.Zum Beispiel ist
::
allein der globale Bereich außerhalb aller anderen Namespaces.some::thing
kann auf eine der folgenden Arten interpretiert werden:some
ist ein Namespace (im globalen Bereich oder ein äußerer Bereich als der aktuelle) undthing
ist ein Typ , eine Funktion , ein Objekt oder ein verschachtelter Namespace ;some
ist eine Klasse, die im aktuellen Bereich verfügbarthing
ist und ein Mitgliedsobjekt , eine Funktion oder ein Typ dersome
Klasse ist;some
kann eine sein , Basistyp des aktuellen Typs (oder den aktuellen Typs selbst) , undthing
ist dann ein Mitglied dieser Klasse, eine Art , Funktion oder Objekt .Sie können auch einen verschachtelten Bereich haben, wie in
some::thing::bad
. Hier kann jeder Name ein Typ, ein Objekt oder ein Namespace sein. Darüber hinaus könnte der letztebad
auch eine Funktion sein. Die anderen konnten dies nicht, da Funktionen nichts innerhalb ihres internen Bereichs verfügbar machen können.Zurück zu Ihrem Beispiel
::thing
kann also nur etwas im globalen Bereich sein: ein Typ, eine Funktion, ein Objekt oder ein Namespace.Die Art und Weise, wie Sie es verwenden, legt nahe (in einer Zeigerdeklaration verwendet), dass es sich um einen Typ im globalen Bereich handelt.
Ich hoffe, diese Antwort ist vollständig und korrekt genug, um Ihnen das Verständnis der Bereichsauflösung zu erleichtern.
quelle
class some { protected: int thing; }; class some_ext : public some { float thing; void action(){ some::thing = 42; thing = 666; } };
Hiersome
ist eine Basisklasse vonsome_ext
und wenn Siesome::thing
in Mitgliedsfunktionen von some_ext schreiben , bedeutet dies dasthing
Objekt in den Basistypsome
. Ohnesome::
,thing
allein mittels derthing
im engsten Umfang, dhsome_ext::thing
. Ist es klarer?::
wird verwendet, um etwas (eine Variable, eine Funktion, eine Klasse, ein typedef usw.) mit einem Namespace oder einer Klasse zu verknüpfen.Wenn es vorher keine linke Seite gibt
::
, unterstreicht dies die Tatsache, dass Sie den globalen Namespace verwenden.z.B:
::doMyGlobalFunction();
quelle
Der als Bereichsauflösungsoperator bezeichnete versteckte globale Name kann mit dem Bereichsauflösungsoperator referenziert werden:
Zum Beispiel;
quelle
(Diese Antwort ist hauptsächlich für Googler gedacht, da OP sein Problem bereits gelöst hat.) Die Bedeutung des vorangestellten
::
Operators für die Bereichsauflösung wurde in anderen Antworten beschrieben, aber ich möchte hinzufügen, warum die Benutzer sie verwenden.Die Bedeutung ist "Name aus globalem Namespace übernehmen, nichts anderes". Aber warum sollte dies explizit geschrieben werden müssen?
Anwendungsfall - Namespace-Konflikt
Wenn Sie im globalen Namespace und im lokalen / verschachtelten Namespace denselben Namen haben, wird der lokale verwendet. Wenn Sie also die globale Version möchten, stellen Sie sie voran
::
. Dieser Fall wurde in der Antwort von @Wyatt Anderson beschrieben, siehe sein Beispiel.Anwendungsfall - Hervorheben der Nichtmitgliedsfunktion
Wenn Sie eine Member-Funktion (eine Methode) schreiben, sehen Aufrufe an andere Member-Funktionen und Aufrufe an Nicht-Member-Funktionen (kostenlos) ähnlich aus:
Aber es kann vorkommen, dass
Twist
es sich um eine Schwesterfunktion der KlasseA
handelt undBend
es sich um eine freie Funktion handelt. Das heißt,Twist
kann verwenden und ändernm_couner
undBend
kann nicht. Wenn Sie also sicherstellen möchten, dassm_counter
0 bleibt, müssen Sie dies überprüfenTwist
, müssen es jedoch nicht überprüfenBend
.Um dies deutlicher hervorzuheben, kann man entweder schreiben
this->Twist
, um dem Leser zu zeigen, dassTwist
es sich um eine Mitgliedsfunktion handelt, oder schreiben::Bend
, um zu zeigen, dassBend
es kostenlos ist. Oder beides. Dies ist sehr nützlich, wenn Sie ein Refactoring durchführen oder planen.quelle
::
ist ein Operator zum Definieren des Namespace.Wenn Sie beispielsweise cout verwenden möchten, ohne dies
using namespace std;
in Ihrem Code zu erwähnen , schreiben Sie Folgendes:Wenn kein Namespace erwähnt wird, heißt es, dass die Klasse zum globalen Namespace gehört.
quelle
"::" steht für den Bereichsauflösungsoperator. Funktionen / Methoden mit demselben Namen können in zwei verschiedenen Klassen definiert werden. Für den Zugriff auf die Methoden eines bestimmten Klassenbereichs wird der Auflösungsoperator verwendet.
quelle