C++ 什么是嵌套名称说明符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4103756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is a nested name specifier?
提问by Glenn
Related to this
与此有关
I want to know what exactly is a nested name specifier? I looked up in the draft but I could understand the grammar as I haven't taken any Compiler Design classes yet.
我想知道嵌套名称说明符到底是什么?我查了一下草稿,但我能理解语法,因为我还没有参加任何编译器设计课程。
void S(){}
struct S{
S(){cout << 1;}
void f(){}
static const int x = 0;
};
int main(){
struct S *p = new struct ::S;
p->::S::f();
S::x;
::S(); // Is ::S a nested name specifier?
delete p;
}
回答by James McNellis
::S
is a qualified-id.
::S
是一个合格的 id。
In the qualified-id::S::f
, S::
is a nested-name-specifier.
在qualified-id 中::S::f
,S::
是一个nested-name-specifier。
In informal terms1, a nested-name-specifieris the part of the idthat
在非正式方面1,一个嵌套的名称说明符是部分ID是
- begins either at the very beginning of a qualified-idor after the initial scope resolution operator (
::
) if one appears at the very beginning of the idand - ends with the last scope resolution operator in the qualified-id.
- 在限定 id的最开头或在初始范围解析运算符 (
::
) 之后开始,如果一个出现在id的最开头,并且 - 以qualified-id 中的最后一个范围解析运算符结束。
Very informally1, an idis either a qualified-idor an unqualified-id. If the idis a qualified-id, it is actually composed of two parts: a nested-name specifier followed by an unqualified-id.
非常非正式地1,一个id要么是qualified-id,要么是unqualified-id。如果id是qualified-id,它实际上由两部分组成:一个nested-name 说明符,后跟一个unqualified-id。
Given:
鉴于:
struct A {
struct B {
void F();
};
};
A
is an unqualified-id.::A
is a qualified-idbut has no nested-name-specifier.A::B
is a qualified-idandA::
is a nested-name-specifier.::A::B
is a qualified-idandA::
is a nested-name-specifier.A::B::F
is a qualified-idand bothB::
andA::B::
are nested-name-specifiers.::A::B::F
is a qualified-idand bothB::
andA::B::
are nested-name-specifiers.
A
是一个不合格的 id。::A
是一个qualified-id,但没有nested-name-specifier。A::B
是一个限定 ID并且A::
是一个嵌套名称说明符。::A::B
是一个限定 ID并且A::
是一个嵌套名称说明符。A::B::F
是一个qualified-id,B::
并且A::B::
都是nested-name-specifiers。::A::B::F
是一个qualified-id,B::
并且A::B::
都是nested-name-specifiers。
[1] This is quite an inexact description. It's hard to describe a grammar in plain English...
[1] 这是一个相当不准确的描述。很难用简单的英语描述语法......
回答by Tony Delroy
A nested namespace specifier is:
嵌套命名空间说明符是:
nested-name-specifier :
class-or-namespace-name::nested-name-specifier(optional)
That is, a non-empty list of namespaces and classnames, each followed by ::, representing a relative branching in the overall "namespace tree" of the program. For example, my_namespace::
, my_namespace::inner_namespace::
, my_namespace::my_class::
, and my_class::
.
也就是说,名称空间和类名的非空列表,每个名称后跟 ::,代表程序整体“名称空间树”中的相对分支。例如,my_namespace::
,my_namespace::inner_namespace::
,my_namespace::my_class::
,和my_class::
。
Note specifically the difference from:
请特别注意与以下内容的区别:
qualified-namespace-specifier :
::(optional) nested-name-specifier(optional) class-or-namespace-name
In that a nested-name-specifier may not be absolute (prefixed with ::
to refer to the global scope), while a qualified-namespace-specifier can be, but doesn't end with ::
.
因为嵌套名称说明符可能不是绝对的(以::
引用全局范围为前缀),而限定名称空间说明符可以是,但不以::
.
In your example, ::S
resolves to the function ::S()
, and not the struct (precendence rules for that were discussed here on Stackoverflow in the question you linked to at the start of your question), so it is not a nested name specifier.
在您的示例中,::S
解析为 function ::S()
,而不是 struct (在您在问题开头链接的问题中在 Stackoverflow 上讨论了该优先规则),因此它不是嵌套名称说明符。
回答by iGbanam
Good question! I learnt something new researching and experimenting on it.
好问题!我学到了一些新的研究和实验。
You are right in your comment, ::S(); //Is ::S a nested name specifier <-- Yes, Indeed!
你的评论是对的, ::S(); //Is ::S a nested name specifier <-- Yes, Indeed!
You would come to appreciate it when you start creating namespaces. Variables can have the same names across namespaces and the ::
operator is what distinguishes them. Namespaces are like classes in a sense, another layer of abstraction. I wouldn't want to bore you with namespaces. You may not appreciate the nested name specifier in this example...consider this one:
当您开始创建命名空间时,您会开始欣赏它。变量可以在命名空间中具有相同的名称,而::
运算符就是区分它们的地方。命名空间在某种意义上就像类,是另一层抽象。我不想让你厌烦命名空间。您可能不喜欢此示例中的嵌套名称说明符……考虑一下这个:
#include <iostream>
using namespace std;
int count(0); // Used for iteration
class outer {
public:
static int count; // counts the number of outer classes
class inner {
public:
static int count; // counts the number of inner classes
};
};
int outer::count(42); // assume there are 42 outer classes
int outer::inner::count(32768); // assume there are 2^15 inner classes
// getting the hang of it?
int main() {
// how do we access these numbers?
//
// using "count = ?" is quite ambiguous since we don't explicitly know which
// count we are referring to.
//
// Nested name specifiers help us out here
cout << ::count << endl; // The iterator value
cout << outer::count << endl; // the number of outer classes instantiated
cout << outer::inner::count << endl; // the number of inner classes instantiated
return 0;
}
Notice that I used ::count
where I could have simply used count
. ::count
refers to the global namespace.
请注意,我::count
在本可以简单使用的地方使用了count
. ::count
指的是全局命名空间。
So in your case, since S() is in the global namespace (i.e. it's declared in the same file or an included file or any piece of code where it's not enveloped by namespace <name_of_namespace> { }
, you could use new struct ::S
or new struct S
; whichever you prefer.
因此,在您的情况下,由于 S() 位于全局命名空间中(即,它在同一文件或包含文件或任何未被 包围的代码中声明namespace <name_of_namespace> { }
,您可以使用new struct ::S
或new struct S
; 无论您喜欢哪个。
I just learnt this as I was curious to answer this question so if you have a more specific and learned answer, please do share :)
我刚刚了解到这一点,因为我很想回答这个问题,所以如果您有更具体和更深入的答案,请分享:)