前缀双冒号“::”是什么意思?

What is the meaning of prepended double colon "::"?

提问人:rmbianchi 提问时间:11/25/2010 最后编辑:Jan Schultkermbianchi 更新时间:9/9/2023 访问量:264911

问:

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

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

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

我还发现:

typedef ::config::set ConfigSet;
C++ 全局命名空间 scope-resolution-operator

评论

14赞 wkl 11/25/2010
真的不觉得这是一个答案,所以我会评论:en.wikipedia.org/wiki/Scope_resolution_operator。在此上下文中,naked 表示引用 global/anonymous 命名空间中的变量。::

答:

7赞 Vladimir Ivanov 11/25/2010 #1

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

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

std::cout << "test";

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

245赞 Moo-Juice 11/25/2010 #2

运算符称为作用域解析运算符,它就是这样解析作用域。因此,通过在 type-name 前面加上 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;
}

评论

2赞 Harsh 6/16/2022
我对此一无所知,现在它让我感到强大,谢谢!
614赞 Wyatt Anderson 11/25/2010 #3

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

评论

0赞 Azurespot 6/1/2017
放置 2 组双冒号的原因是什么?在此:::Configuration::doStuff(...)
0赞 FCo 6/3/2017
@NoniA。你是在问第二组双冒号是做什么的吗?
1赞 Azurespot 6/4/2017
@WyattAnderson,没有第一组。我想我理解介于两者之间的两个术语是指命名空间或类及其成员。但是第一个呢?::
14赞 hungryWolf 5/1/2018
@Azurespot这就是 OP 提出的问题,这就是这篇文章要回答的问题。它确保使用全局命名空间中的标识符。再看一遍这个例子
1赞 Ethan Maness 6/10/2023
@AbelTom 它们不必具有相同的名称,您应该以不同的方式命名它们。该功能仅在碰巧有需要它的利基情况时才存在。
23赞 Stephane Rolland 11/25/2010 #4

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

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

例如:

::doMyGlobalFunction();

157赞 Tony Delroy 11/25/2010 #5

已经有很多合理的答案了。我会用一个可能对一些读者有所帮助的类比来打个比方。 其工作方式与文件系统目录分隔符 '' 非常相似,在搜索要运行的程序的路径时。考虑:::/

/path/to/executable

这是非常明确的 - 只有文件系统树中该确切位置的可执行文件才能与此规范匹配,而不管有效的 PATH 如何。同样地。。。

::std::cout

...在 C++ 命名空间“树”中同样显式。

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

X11/xterm

...如果被发现,会很高兴地跑,否则,否则.同样,假设您在一个名为 的命名空间中,并且有一个有效的“”,那么....../tmp/X11/xterm/usr/bin/X11/xterm/usr/local/bin/X11/xtermXusing namespace Y

std::cout

...可以在 、 、 和 其他地方找到,因为参数相关查找(ADL,又名 Koenig 查找)。所以,only 非常明确地说明了你指的是哪个对象,但幸运的是,没有人会创建自己的类/结构或命名空间,称为“”,也不会创建任何名为“”的东西,所以在实践中只使用是可以的。::X::std::cout::std::cout::Y::std::cout::std::coutstdcoutstd::cout

值得注意的差异

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

2)在C++中,没有任何前导作用域的名称可以在当前命名空间中匹配,而大多数UNIX shell只有在将..PATH

3)C++总是搜索全局命名空间(就像隐式地拥有你的)。/PATH

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

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

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

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

评论

15赞 Trevor Boyd Smith 9/22/2011
+1 表示良好的类比。类比在IMO作为教学工具的使用还不够。
0赞 Luke Davis 11/14/2022
太好了,非常清楚的答案。
0赞 Toby Speight 6/9/2023
另一个很好的类比是域名 - 明确地植根于全局命名空间,不像.但我想有些读者对此不太熟悉。example.org.example.org
54赞 Klaim 11/25/2010 #6

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

例如,alone 是全局范围,位于所有其他命名空间之外。::

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

  • some是一个命名空间(在全局作用域中,或比当前作用域更外的作用域),并且是一个类型、一个函数、一个对象一个嵌套的命名空间 thing;
  • some是当前作用域中可用的类,并且是该的成员对象函数类型;thingsome
  • 在类成员函数中,可以是当前类型(或当前类型本身)的类型,然后是此类的一个成员,即类型函数对象something

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

因此,回到您的示例,只能是全局范围内的内容:类型、函数、对象或命名空间。::thing

使用它的方式表明(在指针声明中使用)它是全局作用域中的一种类型。

我希望这个答案足够完整和正确,以帮助您了解范围解析。

评论

2赞 Klaim 4/5/2013
@obounaim 考虑此代码 liveworkspace.org/code/3Wabw0$5 这里是 的基类,当你写入 some_ext 的成员函数时,它意味着对象进入基类型。没有 ,alone 表示在最接近的范围内,即 。是不是更清楚了?class some { protected: int thing; }; class some_ext : public some { float thing; void action(){ some::thing = 42; thing = 666; } };somesome_extsome::thingthingsomesome::thingthingsome_ext::thing
13赞 Mustafa Ekici 10/12/2013 #7

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

int x;
void f2()
{
   int x = 1; // hide global x
   ::x = 2; // assign to global x
   x = 2; // assign to local x
   // ...
}
12赞 Steed 10/23/2013 #8

(这个答案主要是针对谷歌员工的,因为OP已经解决了他的问题。 前置的含义 - scope resulution operator - 已在其他答案中描述过,但我想补充一下人们使用它的原因。::

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

用例 - 命名空间冲突

当您在全局命名空间和本地/嵌套命名空间中具有相同的名称时,将使用本地命名空间。因此,如果您想要全局的,请在它前面加上 .安德森@Wyatt回答中描述了这种情况,请看他的例子。::

用例 - 强调非成员功能

编写成员函数(方法)时,对其他成员函数的调用和对非成员(自由)函数的调用如下所示:

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

但它可能会发生 class 的姊妹成员函数,并且是一个自由函数。也就是说,可以使用和修改,不能使用。因此,如果你想确保它保持 0,你必须检查,但你不需要检查。TwistABendTwistm_counerBendm_counterTwistBend

因此,为了更清楚地说明这一点,可以写信向读者显示这是一个成员函数,也可以写信来表明它是自由的。或两者兼而有之。这在进行或计划重构时非常有用。this->TwistTwist::BendBend

0赞 Vaman Acharya 2/21/2019 #9

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