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

我在一个类中发现了这一行代码,我必须修改:

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

我不知道类名前的双冒号是什么意思。否则,我将读到:声明tmpCo作为指向类Configuration对象的指针…但是前面的双冒号把我弄糊涂了。

我还发现:

typedef ::config::set ConfigSet;
249314 次浏览

::是定义命名空间的操作符。

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

std::cout << "test";

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

::操作符被称为作用域解析操作符,它解析作用域。因此,通过在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;
}

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

::用于将某物(变量、函数、类、类型定义等)链接到命名空间或类。

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

例如:

::doMyGlobalFunction();

已经有很多合理的答案了。我将插进一个比喻,可能会帮助一些读者。::的工作原理很像文件系统目录分隔符'/',在搜索你想运行的程序的路径时。考虑:

/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中找到,并且可能由于名字查找 (ADL,又名Koenig查找)而在其他地方找到。所以,只有::std::cout真正明确了你指的是哪个对象,但幸运的是,没有哪个头脑正常的人会创建自己的名为“std”的类/结构或命名空间,也没有任何名为“cout”的东西,所以在实践中只使用std::cout就可以了。

值得注意的差异:

1) shell倾向于使用PATH中的顺序来使用第一个匹配,而c++在你有歧义的时候会给出编译器错误。

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

3) c++总是搜索全局命名空间(比如/隐式地使用你的PATH)。

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

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

和很多事情一样,这是一种平衡。c++标准在std::下放置了许多标识符,这些标识符没有cout那么“唯一”,程序员可能在他们的代码中使用这些标识符来表示完全不同的东西(例如mergeincludesfillgenerateexchangequeuetouppermax)。两个不相关的非标准库使用相同标识符的几率要高得多,因为作者通常不知道或不太知道彼此。库——包括c++标准库——随着时间的推移会改变它们的符号。所有这些都可能在重新编译旧代码时产生歧义,特别是当大量使用cout0s时:在这个空间中你能做的最糟糕的事情是允许头文件中的cout0s逃脱头文件的作用域,这样任意大量的直接和间接客户端代码就无法自己决定使用哪个名称空间以及如何管理歧义。

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

::是作用域解析操作符。它被用来指定某物的范围。

例如,::单独是全局作用域,在所有其他名称空间之外。

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

  • some是一个名称空间(在全局作用域中,或在当前作用域中的外部作用域中),而thing是一个类型函数对象嵌套名称空间;
  • some是当前范围内可用的,而thingsome类的成员对象函数类型;
  • 在类成员函数中some可以是当前类型(或当前类型本身)的基本类型,而thing则是该类的一个成员,类型函数对象

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

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

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

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

它被称为作用域解析操作符,一个隐藏的全局名称可以使用作用域解析操作符::
引用 例如,< / p >

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

(这个答案主要是给谷歌人的,因为OP已经解决了他的问题。) 前置的:: -作用域结果运算符-的含义已在其他答案中描述,但我想补充为什么人们使用它

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

用例-名称空间冲突

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

用例强调非成员函数

当你编写一个成员函数(一个方法)时,调用其他成员函数和调用非成员(free)函数看起来很像:

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

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

因此,为了更清楚地说明这一点,可以写this->Twist来告诉读者Twist是成员函数,也可以写::Bend来表明Bend是自由函数。或两者兼而有之。这在您执行或计划重构时非常有用。

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