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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:32:43  来源:igfitidea点击:

What is a nested name specifier?

c++names

提问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

::Sis a qualified-id.

::S是一个合格的 id

In the qualified-id::S::f, S::is a nested-name-specifier.

qualified-id 中::S::fS::是一个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。如果idqualified-id,它实际上由两部分组成:一个nested-name 说明符,后跟一个unqualified-id

Given:

鉴于:

struct  A {
    struct B {
        void F();
    };
};
  • Ais an unqualified-id.
  • ::Ais a qualified-idbut has no nested-name-specifier.
  • A::Bis a qualified-idand A::is a nested-name-specifier.
  • ::A::Bis a qualified-idand A::is a nested-name-specifier.
  • A::B::Fis a qualified-idand both B::and A::B::are nested-name-specifiers.
  • ::A::B::Fis a qualified-idand both B::and A::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-idB::并且A::B::都是nested-name-specifiers
  • ::A::B::F是一个qualified-idB::并且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, ::Sresolves 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 ::countwhere I could have simply used count. ::countrefers 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 ::Sor new struct S; whichever you prefer.

因此,在您的情况下,由于 S() 位于全局命名空间中(即,它在同一文件或包含文件或任何未被 包围的代码中声明namespace <name_of_namespace> { },您可以使用new struct ::Snew 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 :)

我刚刚了解到这一点,因为我很想回答这个问题,所以如果您有更具体和更深入的答案,请分享:)