prepended double colon"::"是什么意思?

rmb*_*chi 383 c++ syntax namespaces scope-resolution global-namespace

我在类中找到了这行代码,我必须修改它:

::Configuration * tmpCo = m_configurationDB;//pointer to current db
Run Code Online (Sandbox Code Playgroud)

而且我不知道究竟是什么意思是双重冒号前面的类名.没有它我会读:声明tmpCo作为指向类的对象的指针Configuration...但前面的双冒号混淆了我.

我还发现:

typedef ::config::set ConfigSet;
Run Code Online (Sandbox Code Playgroud)

Wya*_*son 460

这可确保从全局命名空间发生解析,而不是从您当前所在的命名空间开始.例如,如果您有两个不同的类Configuration,如下所示:

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(...)
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,它允许您遍历到全局命名空间,因为在这种情况下,您的名称可能会受到另一个命名空间内的新定义的破坏MyApp.

  • OP会问@Azurespot,这是此帖子回答的问题。它确保使用全局名称空间中的标识符。再看一个例子 (6认同)

Moo*_*ice 185

::运算符被称为范围解析运算符,并且就是这样,它解析了范围.因此,通过在其前面加上类型名称,它会告诉编译器在类型的全局名称空间中查找.

例:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我以前不知道这个,现在让我感觉很强大,谢谢! (3认同)

Ton*_*roy 115

已经有很多合理的答案了.我会用一个可能有助于读者的类比来填写. 当您搜索要运行的程序的路径时,它的::工作方式与文件系统目录分隔符' /'非常相似.考虑:

/path/to/executable
Run Code Online (Sandbox Code Playgroud)

这非常明确 - 只有文件系统树中该位置的可执行文件才能匹配此规范,无论PATH生效.同样...

::std::cout
Run Code Online (Sandbox Code Playgroud)

...在C++命名空间"tree"中同样明确.

与这样的绝对路径相比,您可以配置好的UNIX shell(例如zsh)来解析当前目录下的相对路径或PATH环境变量中的任何元素,所以如果PATH=/usr/bin:/usr/local/bin,并且您"在"中/tmp,那么......

X11/xterm
Run Code Online (Sandbox Code Playgroud)

...... /tmp/X11/xterm如果找到了会很开心/usr/bin/X11/xterm,否则就行了/usr/local/bin/X11/xterm.同样地,假设你在名为的命名空间中X,并且有一个" using namespace Y"有效,那么......

std::cout
Run Code Online (Sandbox Code Playgroud)

...可以在任何的发现::X::std::cout,::std::cout,::Y::std::cout,和其他可能的地方由于参数相关查找(ADL,又称Koenig查找).所以,只是::std::cout确切地说明了你的意思究竟是哪个对象,但幸运的是,在他们正确的思想中没有人会创建自己的类/结构或命名空间std,而不是任何名为" cout"的东西,所以在实践中使用只是std::cout很好.

值得注意的差异:

1)shell倾向于使用排序使用第一个匹配PATH,而C++在你不明确时给出编译器错误.

2)在C++中,没有任何领导范围的名字可以在当前的命名空间相匹配,而大多数的UNIX shell只能做,如果你把.PATH.

3)C++总是搜索全局命名空间(就像/隐含你的一样PATH).

关于名称空间和符号显式性的一般讨论

使用绝对::abc::def::..."路径"有时可以帮助您将您与正在使用的任何其他命名空间隔离开来,但实际上并不能控制您的库的客户端代码也使用的内容,甚至是其他库.另一方面,它还将您更紧密地耦合到符号的现有"绝对"位置,并且您错过了名称空间中隐式匹配的优点:更少的耦合,更容易在命名空间之间移动代码,以及更简洁,可读的源代码.

与许多事情一样,这是一种平衡行为.C++标准提出很多下标识符std::是小于"独一无二"的cout,程序员可以使用的东西在他们的代码完全不同的(例如merge,includes,fill,generate,exchange,queue,toupper,max).两个不相关的非标准库具有使用相同标识符的机会要高得多,因为作者通常彼此不了解或不太了解.而库 - 包括C++标准库 - 随着时间的推移会改变它们的符号.所有这些都可能在重新编译旧代码时产生歧义,特别是在大量使用using namespaces时:在这个空间中你可以做的最糟糕的事情就是允许using namespace标头中的s用于转义标头的范围,因此任意大量的直接和间接客户端代码无法自行决定使用哪些名称空间以及如何管理歧义.

因此,领先::是C++程序员工具箱中的一个工具,可以主动消除已知冲突的歧义,和/或消除未来模糊的可能性......

  • +1代表好.类比没有使用足够的IMO作为教学工具. (8认同)

Kla*_*aim 36

::是范围解析运算符.它用于指定某事物的范围.

例如,::在所有其他名称空间之外,单独是全局范围.

some::thing 可以通过以下任何方式解释:

  • some是一个命名空间(在全局范围内,或者是当前范围外的范围),thing是一个类型,一个函数,一个对象或一个嵌套的命名空间 ;
  • some是一个在当前范围内可用的并且thing是一个成员对象,功能类型的的some类;
  • 在类成员函数中,some可以是当前类型的基类型(或当前类型本身),thing然后是此类的一个成员,类型,函数对象.

您也可以拥有嵌套范围,如some::thing::bad.这里每个名称可以是类型,对象或命名空间.另外,最后一个bad也可以是一个函数.其他人不能,因为函数不能在其内部范围内暴露任何东西.

所以,回到你的例子,::thing可能只是全局范围内的东西:类型,函数,对象或命名空间.

您使用它的方式建议(在指针声明中使用)它是全局范围中的类型.

我希望这个答案是完整和正确的,足以帮助您了解范围分辨率.

  • @obounaim考虑这段代码http://liveworkspace.org/code/3Wabw0$5`class some {protected:int thing; }; class some_ext:public some {float thing; void action(){some :: thing = 42; thing = 666; 这里`some`是`some_ext`的基类,当你把`some :: thing`写成some_ext的成员函数时,它意味着`thing`对象进入基类型`some`.没有`some ::`,`thing`就意味着最接近范围内的`thing`,即`some_ext :: thing`.它更清楚了吗? (2认同)

Ste*_*and 14

:: 用于将某些东西(变量,函数,类,类型等等...)链接到命名空间或类.

如果之前没有左侧::,那么它强调了您使用全局命名空间的事实.

例如:

::doMyGlobalFunction();


Mus*_*ici 9

它的调用范围解析运算符,可以使用范围解析运算符来引用隐藏的全局名称::
例如;

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


Ste*_*eed 8

(此答案主要是针对Google员工的,因为OP已经解决了他的问题。)::在其他答案中已经说明了前置的含义-范围重新确定运算符-,但我想补充一下人们为什么使用它。

含义是“从全局名称空间获取名称,而不是其他任何名称”。但是,为什么需要对此进行明确的拼写?

用例-名称空间冲突

当您在全局名称空间和本地/嵌套名称空间中具有相同的名称时,将使用本地名称。因此,如果要使用全局变量,请在前面加上::。@Wyatt Anderson的回答描述了这个案例,请看他的例子。

用例-强调非成员功能

在编写成员函数(方法)时,对其他成员函数的调用和对非成员(自由)函数的调用看起来相似:

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

但是可能Twist是class的姐妹成员函数A,并且Bend是自由函数。也就是说,Twist可以使用和修改m_counerBend不能。因此,如果要确保m_counter保持为0,则必须进行检查Twist,但是不需要进行检查Bend

因此,为了使这一点更加清晰,可以编写this->Twist显示Twist成员功能的阅读器,也::Bend可以显示Bend空闲的成员。或两者。在进行或计划重构时,这非常有用。


Vla*_*nov 5

:: 是定义命名空间的运算符。

例如,如果您想using namespace std;在代码中不提及而使用 cout ,您可以这样写:

std::cout << "test";
Run Code Online (Sandbox Code Playgroud)

当没有提到命名空间时,就说这个类属于全局命名空间。