Qual é o significado de dois-pontos duplos precedidos “::”?

Eu encontrei esta linha de código em uma class que eu tenho que modificar:

::Configuration * tmpCo = m_configurationDB;//pointer to current db 

e eu não sei exatamente o que significa o duplo cólon anexado ao nome da class. Sem isso eu iria ler: declaração de tmpCo como um ponteiro para um object da class Configuration … mas o cólon duplo preponderado me confunde.

Eu também encontrei:

 typedef ::config::set ConfigSet; 

Isso garante que a resolução ocorra a partir do namespace global, em vez de começar no namespace em que você está atualmente. Por exemplo, se você tivesse duas classs diferentes chamadas Configuration forma:

 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(...) } } 

Basicamente, ele permite que você percorra até o namespace global, já que seu nome pode ser prejudicado por uma nova definição dentro de outro namespace, neste caso MyApp .

O operador :: é chamado de operador de resolução de escopo e faz exatamente isso, resolve o escopo. Portanto, ao prefixar um nome de tipo com isso, ele diz ao seu compilador para procurar no namespace global pelo tipo.

Exemplo:

 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; } 

Muitas respostas razoáveis ​​já. Eu vou entrar com uma analogia que pode ajudar alguns leitores. :: funciona muito parecido com o separador de diretório do sistema de arquivos ‘ / ‘, ao pesquisar seu caminho para um programa que você gostaria de executar. Considerar:

 /path/to/executable 

Isso é muito explícito – apenas um executável nesse local exato na tree do sistema de arquivos pode corresponder a essa especificação, independentemente do PATH em vigor. Similarmente…

 ::std::cout 

… é igualmente explícito no namespace “tree” do C ++.

Contrastando com esses caminhos absolutos, você pode configurar boas shells do UNIX (por exemplo, zsh) para resolver caminhos relativos em qualquer elemento na sua variável de ambiente PATH , então se PATH=/usr/bin:/usr/local/bin , então …

 X11/xterm 

… seria feliz executar /usr/bin/X11/xterm se encontrado, senão /usr/local/bin/X11/xterm . Da mesma forma, digamos que você estivesse em um namespace chamado X e tivesse um ” using namespace Y ” em vigor, então …

 std::cout 

… pode ser encontrado em qualquer um dos ::X::std::cout , ::std::cout , ::Y::std::cout , e possivelmente outros lugares devido à pesquisa dependente de argumento (ADL, aka Koenig lookup). Então, somente ::std::cout é realmente explícito sobre exatamente qual object você quer dizer, mas felizmente ninguém em sã consciência jamais criaria sua própria class / estrutura ou namespace chamado ” std “, nem nada chamado ” cout “, portanto praticar usando apenas std::cout é bom.

(Uma diferença notável é que os shells tendem a usar a primeira correspondência usando a ordem no PATH , enquanto o C ++ fornece um erro do compilador quando você é ambíguo).

Discussão geral sobre namespaces e explicitação de símbolos

Usar absolute ::abc::def::... “paths” pode algumas vezes ser útil para isolar você de qualquer outro namespace que você esteja usando, mas não tem controle sobre o conteúdo, ou mesmo sobre outras bibliotecas que o código de cliente da sua biblioteca também usa. Por outro lado, ele também o acopla mais firmemente ao local “absoluto” existente do símbolo, e você perderá as vantagens da correspondência implícita em namespaces: menos acoplamento, mobilidade mais fácil de código entre namespaces e código-fonte mais conciso e legível .

Tal como acontece com muitas coisas, é um ato de equilíbrio. O C ++ Standard coloca muitos identificadores sob std:: que são menos “únicos” que cout , que os programadores podem usar para algo completamente diferente em seu código (por exemplo, merge , includes , fill , generate , exchange , queue , toupper , max ). Duas bibliotecas não-relacionadas não-relacionadas têm uma chance muito maior de usar os mesmos identificadores que os autores geralmente não estão cientes uns dos outros. E as bibliotecas – incluindo a biblioteca C ++ Standard – alteram seus símbolos ao longo do tempo. Tudo isso potencialmente cria ambiguidade ao recompilar código antigo, particularmente quando há um uso pesado do uso de using namespace : a pior coisa que você pode fazer neste espaço é permitir using namespace nos headers para escaping dos escopos dos headers, de modo que uma quantidade arbitrariamente grande de código de cliente direto e indireto é incapaz de tomar suas próprias decisões sobre quais namespaces usar e como gerenciar ambiguidades.

Então, um leading :: é uma ferramenta na checkbox de ferramentas do programador C ++ para ativamente desambiguar um conflito conhecido e / ou eliminar a possibilidade de futura ambigüidade ….

:: é o operador de resolução do escopo. É usado para especificar o escopo de algo.

Por exemplo, :: alone é o escopo global, fora de todos os outros namespaces.

some::thing pode ser interpretada de qualquer das seguintes maneiras:

  • some é um namespace (no escopo global, ou um escopo externo que o atual) e thing é um tipo , uma function , um object ou um namespace nested ;
  • some é uma class disponível no escopo atual e é um object membro , function ou tipo de some class;
  • em uma function de membro de class , some podem ser um tipo base do tipo atual (ou o tipo atual em si) e thing é então um membro dessa class, um tipo , function ou object .

Você também pode ter um escopo nested, como em some::thing::bad . Aqui, cada nome poderia ser um tipo, um object ou um namespace. Além disso, o último, bad , também poderia ser uma function. Os outros não puderam, já que as funções não podem expor nada dentro de seu escopo interno.

Então, voltando ao seu exemplo, ::thing pode ser apenas algo no escopo global: um tipo, uma function, um object ou um namespace.

A maneira como você usa sugere (usado em uma declaração de ponteiro) que é um tipo no escopo global.

Espero que esta resposta esteja completa e correta o suficiente para ajudá-lo a entender a resolução do escopo.

:: é usado para vincular algo (uma variável, uma function, uma class, um typedef etc …) a um namespace ou a uma class.

se não houver o lado esquerdo antes de :: , ele sublinha o fato de você estar usando o namespace global.

por exemplo:

::doMyGlobalFunction();

seu operador de resolução de escopo chamado, Um nome global oculto pode ser referido usando o operador de resolução de escopo ::
Por exemplo;

 int x; void f2() { int x = 1; // hide global x ::x = 2; // assign to global x x = 2; // assign to local x // ... } 

(Essa resposta é principalmente para googlers, porque OP já resolveu seu problema.) O significado de operador de resolução de escopos prepended :: – foi descrito em outras respostas, mas gostaria de acrescentar por que as pessoas o estão usando.

O significado é “pegue o nome do namespace global, nada mais”. Mas por que isso precisaria ser escrito explicitamente?

Caso de uso – conflito de namespace

Quando você tiver o mesmo nome no namespace global e no namespace local / nested, o local será usado. Então, se você quer o global, prefixá-lo com :: . Este caso foi descrito na resposta de @Wyatt Anderson, por favor veja o seu exemplo.

Caso de uso – enfatize a function de não membro

Quando você está escrevendo uma function de membro (um método), chamadas para outra function de membro e chamadas para funções de non-member (livre) são semelhantes:

 class A { void DoSomething() { m_counter=0; ... Twist(data); ... Bend(data); ... if(m_counter>0) exit(0); } int m_couner; ... } 

Mas pode acontecer que Twist seja uma function membro irmã da class A , e Bend seja uma function livre. Ou seja, Twist pode usar e modificar m_couner e Bend não pode. Então, se você quer assegurar que m_counter permaneça 0, você deve checar Twist , mas você não precisa checar Bend .

Então, para fazer isso se destacar mais claramente, pode-se escrever this->Twist para mostrar ao leitor que Twist é uma function-membro ou escrever ::Bend para mostrar que Bend está livre. Ou ambos. Isso é muito útil quando você está fazendo ou planejando uma refatoração.

:: é um operador de definir o namespace.

Por exemplo, se você quiser usar cout sem mencionar o using namespace std; no seu código você escreve isto:

 std::cout < < "test"; 

Quando nenhum namespace é mencionado, diz-se que a class pertence ao namespace global.