525 Stimmen

Was bedeutet der vorangestellte doppelte Doppelpunkt "::"?

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 diesen würde ich lesen: declaration of tmpCo als Zeiger auf ein Objekt der Klasse Configuration ... aber der vorangestellte doppelte Doppelpunkt verwirrt mich.

Ich habe auch gefunden:

typedef ::config::set ConfigSet;

626voto

Wyatt Anderson Punkte 9258

Dadurch wird sichergestellt, dass die Auflösung vom globalen Namespace aus erfolgt, anstatt mit dem Namespace zu beginnen, in dem Sie sich gerade befinden. Wenn Sie zum Beispiel zwei verschiedene Klassen namens Configuration als solche:

class Configuration; // class 1, in global namespace
namespace MyApp
{
    class Configuration; // class 2, different from class 1
    function blah()
    {
        // resolves to MyApp::Configuration, class 2
        Configuration::doStuff(...) 
        // resolves to top-level Configuration, class 1
        ::Configuration::doStuff(...)
    }
}

Grundsätzlich können Sie damit bis zum globalen Namespace traversieren, da Ihr Name durch eine neue Definition in einem anderen Namespace überlagert werden könnte, in diesem Fall MyApp .

247voto

Moo-Juice Punkte 37380

El :: Operator wird als Bereichsauflösungsoperator bezeichnet und tut genau das, er löst den Bereich auf. S

int count = 0;

int main(void) {
  int count = 0;
  ::count = 1;  // set global count to 1
  count = 2;    // set local count to 2
  return 0;
}

160voto

Tony Delroy Punkte 98528

Es gibt bereits viele vernünftige Antworten. Ich werde mich mit einer Analogie einbringen, die einigen Lesern helfen könnte. :: funktioniert ähnlich wie das Dateisystem-Verzeichnistrennzeichen ' / ', wenn Sie Ihren Pfad nach einem Programm durchsuchen, das Sie ausführen möchten. Bedenken Sie:

/path/to/executable

Dies ist sehr eindeutig - nur eine ausführbare Datei an genau dieser Stelle im Dateisystem kann dieser Spezifikation entsprechen, unabhängig vom gültigen PATH. Ähnlich...

::std::cout

...ist im C++-Namensraum "tree" ebenso eindeutig.

Im Gegensatz zu solchen absoluten Pfaden können Sie gute UNIX-Shells (z. B. zsh ) aufzulösen relativ Pfade unter Ihrem aktuellen Verzeichnis oder jedes Element in Ihrem PATH Umgebungsvariable, wenn also PATH=/usr/bin:/usr/local/bin und Sie waren "dabei". /tmp ...dann...

X11/xterm

...würde mit Freude laufen /tmp/X11/xterm wenn gefunden, sonst /usr/bin/X11/xterm sonst /usr/local/bin/X11/xterm . Ähnlich verhält es sich, wenn Sie sich in einem Namespace namens X und hatte einen " using namespace Y " in der Tat, dann...

std::cout

...könnte in einem der folgenden Bereiche zu finden sein ::X::std::cout , ::std::cout , ::Y::std::cout und möglicherweise auch an anderen Orten aufgrund von argumentabhängiges Nachschlagen (ADL, auch bekannt als Koenig Lookup). Also, nur ::std::cout ist wirklich eindeutig, welches Objekt Sie meinen, aber glücklicherweise würde niemand, der bei Verstand ist, jemals eine eigene Klasse/Struktur oder einen Namespace mit dem Namen " std ", noch etwas mit der Bezeichnung " cout ", so dass in der Praxis nur die Verwendung von std::cout ist in Ordnung.

Bemerkenswerte Unterschiede :

1) Muscheln neigen dazu, den ersten Treffer zu verwenden, indem sie die Reihenfolge in PATH während C++ bei Zweideutigkeit einen Compilerfehler ausgibt.

2) In C++ können Namen ohne führenden Scope im aktuellen Namespace gefunden werden, während die meisten UNIX-Shells dies nur tun, wenn Sie . im PATH .

3) C++ durchsucht immer den globalen Namespace (als ob man / implizit Ihr PATH ).

Allgemeine Diskussion über Namensräume und Explizitheit von Symbolen

Verwendung absoluter ::abc::def::... "Pfade" können manchmal nützlich sein, um Sie von anderen Namespaces zu isolieren, die Sie verwenden, von denen Sie Teil sind, über deren Inhalt Sie aber keine wirkliche Kontrolle haben, oder sogar von anderen Bibliotheken, die der Client-Code Ihrer Bibliothek ebenfalls verwendet. Andererseits sind Sie dadurch auch enger an die bestehende "absolute" Position des Symbols gebunden, und Sie verpassen die Vorteile des impliziten Abgleichs in Namespaces: weniger Kopplung, einfachere Mobilität des Codes zwischen Namespaces und prägnanterer, lesbarerer Quellcode.

Wie bei vielen anderen Dingen auch, ist es ein Balanceakt. Der C++ Standard stellt viele Bezeichner unter std:: die weniger "einzigartig" sind als cout die Programmierer für etwas völlig anderes in ihrem Code verwenden könnten (z. B. merge , includes , fill , generate , exchange , queue , toupper , max ). Bei zwei nicht miteinander verbundenen Nicht-Standard-Bibliotheken ist die Wahrscheinlichkeit, dass sie dieselben Bezeichner verwenden, weitaus größer, da sich die Autoren in der Regel nicht oder weniger bewusst sind. Und Bibliotheken - einschließlich der C++-Standardbibliothek - ändern ihre Symbole im Laufe der Zeit. All dies kann beim Neukompilieren von altem Code zu Mehrdeutigkeit führen, insbesondere wenn die folgenden Symbole häufig verwendet wurden using namespace s: Das Schlimmste, was man in diesem Bereich tun kann, ist zuzulassen, dass using namespace s in Headern, um dem Geltungsbereich der Header zu entkommen, so dass eine beliebig große Menge an direktem und indirektem Client-Code nicht in der Lage ist, eigene Entscheidungen darüber zu treffen, welche Namespaces zu verwenden sind und wie mit Mehrdeutigkeiten umzugehen ist.

Also, eine führende :: ist ein Werkzeug im Werkzeugkasten des C++-Programmierers, um einen bekannten Konflikt aktiv zu disambiguieren und/oder die Möglichkeit künftiger Mehrdeutigkeiten zu beseitigen....

55voto

Klaim Punkte 63705

:: ist der Operator für die Bereichsauflösung. Er wird verwendet, um den Geltungsbereich von etwas anzugeben.

Zum Beispiel, :: allein ist der globale Bereich, außerhalb aller anderen Namensräume.

some::thing kann auf eine der folgenden Arten interpretiert werden:

  • some ist eine Namensraum (im globalen Bereich oder in einem anderen Bereich als dem aktuellen) und thing ist eine Typ , a Funktion an Objekt oder eine verschachtelter Namensraum ;
  • some ist eine Klasse im aktuellen Geltungsbereich verfügbar und thing ist eine Mitgliedsobjekt , Funktion o Typ der some Klasse;
  • in einer Mitgliedsfunktion der Klasse , some kann ein Basistyp des aktuellen Typs (oder des aktuellen Typs selbst) und thing ist dann ein Mitglied dieser Klasse, ein Typ , Funktion o Objekt .

Sie können auch verschachtelte Bereiche haben, wie in some::thing::bad . Hier könnte jeder Name ein Typ, ein Objekt oder ein Namespace sein. Darüber hinaus ist der letzte, bad könnte auch eine Funktion sein. Die anderen könnten es nicht sein, da Funktionen innerhalb ihres internen Bereichs nichts preisgeben können.

Also, zurück zu Ihrem Beispiel, ::thing kann 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), dass es ein Typ im globalen Bereich ist.

Ich hoffe, diese Antwort ist vollständig und korrekt genug, um Ihnen zu helfen, die Auflösung des Geltungsbereichs zu verstehen.

23voto

Stephane Rolland Punkte 36818

:: wird verwendet, um etwas (eine Variable, eine Funktion, eine Klasse, ein Typedef etc...) mit einem Namespace oder einer Klasse zu verbinden.

wenn es keine linke Seite vor :: dann unterstreicht es die Tatsache, dass Sie den globalen Namespace verwenden.

z.B.:

::doMyGlobalFunction();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X