476

我在一个必须修改的类中找到了这行代码:

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

而且我不知道类名前面的双冒号到底是什么意思。没有它,我会读到:声明tmpCo为指向类对象的指针Configuration......但前面的双冒号让我感到困惑。

我还发现:

typedef ::config::set ConfigSet;
4

9 回答 9

562

这确保了从全局命名空间进行解析,而不是从您当前所在的命名空间开始。例如,如果您有两个不同的类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(...)
    }
}

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

于 2010-11-24T16:27:38.260 回答
220

::运算符称为范围解析运算符,它就是这样做的,它解析范围。因此,通过在类型名称前加上 this 前缀,它会告诉编译器在全局命名空间中查找该类型。

例子:

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;
}
于 2010-11-24T16:27:16.540 回答
141

已经有很多合理的答案了。我会打个比方,可能对一些读者有所帮助。 在搜索您想要运行的程序的路径时,它的::工作原理很像文件系统目录分隔符“ ”。/考虑:

/path/to/executable

这是非常明确的——只有文件系统树中那个确切位置的可执行文件才能匹配这个规范,而不管有效的 PATH 是什么。相似地...

::std::cout

...在 C++ 命名空间“树”中同样明确。

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

X11/xterm

.../tmp/X11/xterm如果找到,会很高兴地运行,否则/usr/bin/X11/xterm,否则/usr/local/bin/X11/xterm。同样,假设您在一个名为 的命名空间中X,并且实际上有一个“ using namespace Y”,那么......

std::cout

...由于依赖于参数的查找(ADL,又名 Koenig 查找),可以在 、 、 和其他任何::X::std::cout地方::std::cout找到。所以,only真的很明确你的意思是哪个对象,但幸运的是,没有人会在他们的头脑中创建自己的名为“”的类/结构或命名空间,也不会创建任何名为“ ”的东西,所以在实践中使用 only就可以了。::Y::std::cout::std::coutstdcoutstd::cout

值得注意的差异

1) shell 倾向于使用 in 中的排序来使用第一个匹配项PATH,而 C++ 在您模棱两可时会给出编译器错误。

2) 在 C++ 中,没有任何前导范围的名称可以在当前命名空间中匹配,而大多数 UNIX shell 仅在您.PATH.

3) C++ 总是搜索全局命名空间(比如/隐含你的PATH)。

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

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

与许多事情一样,这是一种平衡行为。C++ 标准在其下放置了许多std::不那么“唯一”的标识符,程序员可能会在他们的代码中cout用于完全不同的东西(例如merge,、、、、、、、、、includes)。两个不相关的非标准库使用相同标识符的机会要高得多,因为作者通常不知道或不知道彼此。库——包括 C++ 标准库——会随着时间的推移而改变它们的符号。所有这些都可能在重新编译旧代码时产生歧义,特别是在大量使用s 时:在这个领域你能做的最糟糕的事情就是允许fillgenerateexchangequeuetouppermaxusing namespaceusing namespaces 在标头中转义标头的范围,这样任意大量的直接和间接客户端代码无法自行决定使用哪些命名空间以及如何管理歧义。

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

于 2010-11-24T16:42:45.113 回答
45

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

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

some::thing可以用以下任何一种方式来解释:

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

您还可以有嵌套范围,如some::thing::bad. 这里的每个名称都可以是一个类型、一个对象或一个命名空间。此外,最后一个 ,bad也可以是一个函数。其他人不能,因为函数不能在其内部范围内公开任何内容。

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

您使用它的方式表明(在指针声明中使用)它是全局范围内的类型。

我希望这个答案足够完整和正确,可以帮助您理解范围分辨率。

于 2010-11-24T16:43:26.273 回答
20

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

如果之前没有左侧::,则它强调了您正在使用全局命名空间的事实。

例如:

::doMyGlobalFunction();

于 2010-11-24T16:29:02.127 回答
11

其称为作用域解析操作符,一个隐藏的全局名称可以使用作用域解析操作符来引用::
例如;

int x;
void f2()
{
   int x = 1; // hide global x
   ::x = 2; // assign to global x
   x = 2; // assign to local x
   // ...
}
于 2013-10-11T17:59:10.767 回答
11

(这个答案主要是针对谷歌员工的,因为 OP 已经解决了他的问题。) 前置::- 范围结果运算符 - 的含义已在其他答案中进行了描述,但我想补充一下人们使用它的原因。

意思是“从全局命名空间中取名,而不是其他任何东西”。但是为什么需要明确地拼写呢?

用例 - 命名空间冲突

当您在全局命名空间和本地/嵌套命名空间中具有相同名称时,将使用本地名称。所以如果你想要全局的,在它前面加上::. @Wyatt Anderson 的回答中描述了这种情况,请参阅他的示例。

用例——强调非成员函数

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

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

但它可能Twist是 class 的姐妹成员函数A,并且Bend是一个自由函数。即Twist可以使用和修改m_counerBend不能。所以如果你想确保m_counter保持为0,你必须检查Twist,但你不需要检查Bend

因此,为了使这一点更清楚,可以写给this->Twist读者看它Twist是一个成员函数,也可以写给::BendBend是免费的。或两者。这在您进行或计划重构时非常有用。

于 2013-10-23T13:04:17.333 回答
6

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

例如,如果您想using namespace std;在代码中不提及的情况下使用 cout,请编写以下代码:

std::cout << "test";

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

于 2010-11-24T16:26:11.757 回答
2

“::”表示范围解析运算符。可以在两个不同的类中定义具有相同名称的函数/方法。访问特定类范围解析运算符的方法被使用。

于 2019-02-20T17:39:05.187 回答