提问人:rmbianchi 提问时间:11/25/2010 最后编辑:Jan Schultkermbianchi 更新时间:9/9/2023 访问量:264911
前缀双冒号“::”是什么意思?
What is the meaning of prepended double colon "::"?
问:
我在必须修改的类中找到了这一行代码:
::Configuration * tmpCo = m_configurationDB;//pointer to current db
而且我不知道类名前面的双冒号到底是什么意思。如果没有它,我会读到:声明为指向类对象的指针......但是前面的双冒号让我感到困惑。tmpCo
Configuration
我还发现:
typedef ::config::set ConfigSet;
答:
::
是定义命名空间的运算符。
例如,如果你想在代码中不提及 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
评论
::Configuration::doStuff(...)
::
::
用于将某些内容(变量、函数、类、typedef 等)链接到命名空间或类。
如果前面没有左侧,则它强调了您正在使用全局命名空间的事实。::
例如:
::doMyGlobalFunction();
已经有很多合理的答案了。我会用一个可能对一些读者有所帮助的类比来打个比方。 其工作方式与文件系统目录分隔符 '' 非常相似,在搜索要运行的程序的路径时。考虑:::
/
/path/to/executable
这是非常明确的 - 只有文件系统树中该确切位置的可执行文件才能与此规范匹配,而不管有效的 PATH 如何。同样地。。。
::std::cout
...在 C++ 命名空间“树”中同样显式。
与这种绝对路径相比,您可以配置良好的 UNIX shell(例如 zsh)来解析当前目录下或环境变量中任何元素下的相对路径,因此,如果 ,并且您是 “in” ,那么......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
...可以在 、 、 和 其他地方找到,因为参数相关查找(ADL,又名 Koenig 查找)。所以,only 非常明确地说明了你指的是哪个对象,但幸运的是,没有人会创建自己的类/结构或命名空间,称为“”,也不会创建任何名为“”的东西,所以在实践中只使用是可以的。::X::std::cout
::std::cout
::Y::std::cout
::std::cout
std
cout
std::cout
值得注意的差异:
1)shell倾向于使用排序的第一个匹配项,而C++在你模棱两可时给出编译器错误。PATH
2)在C++中,没有任何前导作用域的名称可以在当前命名空间中匹配,而大多数UNIX shell只有在将..
PATH
3)C++总是搜索全局命名空间(就像隐式地拥有你的)。/
PATH
关于命名空间和符号显式性的一般性讨论
使用绝对“路径”有时有助于将您与正在使用的任何其他命名空间隔离开来,这些命名空间是库的一部分,但实际上无法控制其内容,甚至是库的客户端代码也使用的其他库。另一方面,它也会将您更紧密地耦合到符号的现有“绝对”位置,并且您错过了命名空间中隐式匹配的优点:更少的耦合,代码在命名空间之间的移动更容易,以及更简洁、可读的源代码。::abc::def::...
与许多事情一样,这是一种平衡行为。C++ 标准将许多标识符放在下面,这些标识符的“唯一性”不如 ,程序员可能会在他们的代码中用于完全不同的东西(例如,,,,)。两个不相关的非标准库使用相同标识符的几率要高得多,因为作者通常彼此不了解或不太了解。库(包括 C++ 标准库)会随着时间的推移而改变其符号。在重新编译旧代码时,所有这些都可能会产生歧义,尤其是当大量使用 s 时:在这个空间中,你能做的最糟糕的事情是允许标头中的 s 转义标头的作用域,这样任意大量的直接和间接客户端代码就无法自行决定使用哪些命名空间以及如何管理歧义。std::
cout
merge
includes
fill
generate
exchange
queue
toupper
max
using namespace
using namespace
因此,领先是C++程序员工具箱中的一种工具,用于主动消除已知冲突的歧义,和/或消除未来歧义的可能性。::
评论
example.org.
example.org
::
是范围解析运算符。它用于指定某事的范围。
例如,alone 是全局范围,位于所有其他命名空间之外。::
some::thing
可以用以下任何一种方式解释:
some
是一个命名空间(在全局作用域中,或比当前作用域更外的作用域),并且是一个类型、一个函数、一个对象或一个嵌套的命名空间thing
;some
是当前作用域中可用的类,并且是该类的成员对象、函数或类型;thing
some
- 在类成员函数中,可以是当前类型(或当前类型本身)的基类型,然后是此类的一个成员,即类型、函数或对象。
some
thing
也可以有嵌套作用域,如 。在这里,每个名称可以是一个类型、一个对象或一个命名空间。此外,最后一个 ,也可以是一个函数。其他人不能,因为函数不能在其内部范围内公开任何内容。some::thing::bad
bad
因此,回到您的示例,只能是全局范围内的内容:类型、函数、对象或命名空间。::thing
使用它的方式表明(在指针声明中使用)它是全局作用域中的一种类型。
我希望这个答案足够完整和正确,以帮助您了解范围解析。
评论
class some { protected: int thing; }; class some_ext : public some { float thing; void action(){ some::thing = 42; thing = 666; } };
some
some_ext
some::thing
thing
some
some::
thing
thing
some_ext::thing
其称为作用域解析运算符,可以使用作用域解析运算符引用隐藏的全局名称::
例如;
int x;
void f2()
{
int x = 1; // hide global x
::x = 2; // assign to global x
x = 2; // assign to local x
// ...
}
(这个答案主要是针对谷歌员工的,因为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,你必须检查,但你不需要检查。Twist
A
Bend
Twist
m_couner
Bend
m_counter
Twist
Bend
因此,为了更清楚地说明这一点,可以写信向读者显示这是一个成员函数,也可以写信来表明它是自由的。或两者兼而有之。这在进行或计划重构时非常有用。this->Twist
Twist
::Bend
Bend
“::” 表示范围解析运算符。 具有相同名称的函数/方法可以在两个不同的类中定义。若要访问特定类的方法,请使用范围解析运算符。
评论
::