prepend双冒号“::”是什么意思?
我在一个类中find了这行代码,我必须修改它:
::Configuration * tmpCo = m_configurationDB;//pointer to current db
而且我不知道到底是什么意味着类名前缀的双冒号。 没有这个我会读: tmpCo
声明作为指向Configuration
类的对象的指针…但前缀的双冒号混淆了我。
我还发现:
typedef ::config::set ConfigSet;
这确保parsing发生在全局命名空间中,而不是从当前所在的命名空间开始。例如,如果您有两个不同的名为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
。
::
运算符被称为作用域parsing运算符,只是这样做,它解决了范围。 所以,通过在types名称前加上这个名称,它会告诉编译器在types的全局名称空间中查找。
例:
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; }
已经有很多合理的答案。 我会用一个比喻来帮助一些读者。 ::
在search你想要运行的程序的path时,与文件系统目录分隔符“ /
”非常相似。 考虑:
/path/to/executable
这是非常明确的 – 只有在文件系统树中精确位置的可执行文件可以匹配这个规范,而不pipePATH有效。 同样…
::std::cout
…在C ++命名空间“树”中同样明确。
与这种绝对path相比,你可以configuration好的UNIX shell(例如zsh)来parsingPATH
环境variables中任何元素下的相对path,所以如果PATH=/usr/bin:/usr/local/bin
,那么…
X11/xterm
…会很高兴地运行/usr/bin/X11/xterm
如果find),否则/usr/local/bin/X11/xterm
。 同样,假设你在一个名为X
的命名空间中,并且有一个“ using namespace Y
”,那么…
std::cout
…可以在::X::std::cout
, ::std::cout
, ::Y::std::cout
,也可能在其他地方由于依赖于参数的查找 (ADL,aka Koenig查找)。 所以,只有::std::cout
确切地说明了你指的是哪一个对象,但幸运的是,他们正确的思想中没有人会创build自己的类/结构或称为“ std
”的名字空间,也没有任何名为“ cout
”练习只使用std::cout
是好的。
(一个值得注意的区别是,shell倾向于使用PATH
的顺序使用第一个匹配,而C ++在给出模糊的时候会给出编译器错误。)
关于命名空间和符号显式的一般性讨论
使用绝对::abc::def::...
“path”有时可以用来隔离你使用的任何其他名称空间,其中一部分但不真正控制内容,甚至是其他库您的图书馆的客户代码也使用。 另一方面,它也将你更紧密地耦合到符号的现有“绝对”位置,而且你错过了命名空间中隐式匹配的优点:耦合less,名称空间之间的代码更容易移动,以及更简洁可读的源代码。
和许多事情一样,这是一个平衡的行为。 C ++标准在std::
中放置了很多标识符,这些标识符比cout
更“独特”,程序员可以在代码中使用完全不同的东西(例如merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
)。 两个不相关的非标准库使用相同标识符的可能性要高得多,因为作者通常彼此之间不太了解。 包括C ++标准库在内的库随着时间的推移而改变它们的符号。 所有这些都可能在重新编译旧代码时产生歧义,特别是在大量使用using namespace
的情况下:在这个空间中最糟糕的事情是允许在头文件中using namespace
来转义头文件的作用域,从而使任意大量的直接和间接的客户端代码无法自行决定使用哪个命名空间以及如何pipe理歧义。
因此,领先的::
是C ++程序员的工具箱中的一个工具,用于主动消除已知的冲突,和/或消除将来模糊的可能性….
::
是范围parsing运算符。 它用来指定一些东西的范围。
例如, ::
alone是所有其他名称空间之外的全局作用域。
some::thing
可以用以下任何一种方式解释:
-
some
是名称空间 (在全局范围内,或者是当前的外部范围),thing
是一个types ,一个函数 ,一个对象或者一个嵌套的命名空间 ; -
some
是当前范围内可用的类 ,thing
是某个类的成员对象 , 函数或types ; - 在一个类成员函数中 ,
some
可以是当前types(或者当前types本身)的基types ,而thing
则是这个类的一个成员, types , 函数或者对象 。
你也可以嵌套作用域,就像在some::thing::bad
。 这里每个名字可以是一个types,一个对象或一个名字空间。 另外,最后一个bad
,也可能是一个function。 其他人不能,因为函数不能暴露其内部范围内的任何东西。
所以,回到你的例子中, ::thing
只能是全局范围内的东西:一个types,一个函数,一个对象或者一个名字空间。
你使用它的方式build议(在一个指针声明中使用)它是全局作用域中的一个types。
我希望这个答案是完整和正确的,以帮助您了解范围解决scheme。
::
用于将某些东西(一个variables,一个函数,一个类,一个typedef等)链接到一个名称空间或一个类。
如果在::
之前没有左手边,那么它强调了你正在使用全局命名空间的事实。
例如:
::doMyGlobalFunction();
它被称为作用域parsing运算符,隐藏的全局名称可以使用作用域parsing运算符来引用::
例如;
int x; void f2() { int x = 1; // hide global x ::x = 2; // assign to global x x = 2; // assign to local x // ... }
(这个答案主要是针对google的,因为OP已经解决了他的问题。)prepend ::
– scope resulution操作符的含义已经在其他答案中描述过,但是我想补充为什么人们使用它。
其含义是“从全局命名空间取名字,而不是其他任何东西”。 但为什么需要明确拼写呢?
用例 – 命名空间冲突
在全局名称空间和本地/嵌套名称空间中具有相同名称时,将使用本地名称空间。 所以如果你想要全局的话,可以用::
前缀。 @Wyatt Anderson的回答中描述了这种情况,请看他的例子。
用例 – 强调非成员函数
当你写一个成员函数(一个方法)时,调用其他成员函数和调用非成员(免费)函数看起来一样:
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
是免费的。 或两者。 这在您正在执行或计划重构时非常有用。
::
是定义名称空间的操作符。
例如,如果你想使用cout而不提及using namespace std;
在你的代码中你写这个:
std::cout << "test";
当没有提到名称空间时,就说该类属于全局名称空间。