prepended double colon“::”是什么意思?

问题描述 投票:354回答:9

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

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

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

我还发现:

typedef ::config::set ConfigSet;
c++ syntax namespaces scope-resolution global-namespace
9个回答
445
投票

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


179
投票

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

例:

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

108
投票

已经有很多合理的答案了。我将通过一个可能有助于一些读者的类比来填写。 ::的工作原理很像文件系统目录分隔符'/',当你在路径中搜索你想要运行的程序时。考虑:

/path/to/executable

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

::std::cout

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

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

X11/xterm

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

std::cout

......可以在任何::X::std::cout::std::cout::Y::std::cout以及其他地方找到argument-dependent lookup(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那样“独特”的标识符,程序员可能会在代码中使用完全不同的东西(例如mergeincludesfillgenerateexchangequeuetouppermax)。两个不相关的非标准库具有使用相同标识符的机会要高得多,因为作者通常彼此不了解或不太了解。而库 - 包括C ++标准库 - 随着时间的推移会改变它们的符号。所有这些都可能在重新编译旧代码时产生歧义,特别是当大量使用using namespaces时:在这个空间中你可以做的最糟糕的事情是允许标题中的using namespaces逃避标题的范围,这样任意大量的直接和间接客户端代码无法自行决定使用哪些命名空间以及如何管理歧义。

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


35
投票

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

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

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

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

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

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

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

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


14
投票

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

如果在::之前没有左手边,那么它强调了你正在使用全局命名空间的事实。

e.g:

::doMyGlobalFunction();


9
投票

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

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

6
投票

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

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

用例 - 命名空间冲突

如果在全局命名空间和本地/嵌套命名空间中具有相同的名称,则将使用本地命名空间。所以如果你想要全局的那个,请用::作为前缀。这个案例在@Wyatt Anderson的回答中有所描述,请看他的例子。

用例 - 强调非成员函数

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

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

但是可能会发生TwistA类的姐妹成员函数,而Bend是一个自由函数。也就是说,Twist可以使用和修改m_counerBend不能。因此,如果你想确保m_counter保持为0,你必须检查Twist,但你不需要检查Bend

因此,要更清楚地突出这一点,可以写this->Twist向读者展示Twist是成员函数或写::Bend以表明Bend是免费的。或两者。当您进行或计划重构时,这非常有用。


3
投票

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

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

std::cout << "test";

如果没有提到名称空间,则表示该类属于全局名称空间。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.