Что такое спецификатор вложенного имени? - PullRequest
29 голосов
/ 05 ноября 2010

Относится к this

Я хочу знать, что именно является спецификатором вложенного имени?Я посмотрел в черновике, но я мог понять грамматику, так как я еще не изучал классы Compiler Design.

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;
} 

Ответы [ 3 ]

34 голосов
/ 05 ноября 2010

::S является квалифицированным идентификатором .

В квалифицированном идентификаторе ::S::f, S:: является спецификатором вложенного имени .

В неформальных терминах 1 , спецификатор вложенного имени является частью id , который

  • начинается либо в самом начале квалифицированный идентификатор или после начального оператора разрешения области (::), если он появляется в самом начале id и
  • , заканчивается последним оператором разрешения области в квалифицированный идентификатор .

Очень неформально 1 , идентификатор является либо квалифицированным идентификатором , либо безусловный идентификатор .Если id является квалифицированным идентификатором , он фактически состоит из двух частей: спецификатора вложенного имени, за которым следует безусловный идентификатор .

Дано:

struct  A {
    struct B {
        void F();
    };
};
  • A является безусловным идентификатором .
  • ::A является квалифицированным идентификатором , но не имеет спецификатора вложенного имени .
  • A::B является квалифицированным идентификатором , а A:: является вложенным именем-спецификатор .
  • ::A::B является квалифицированным идентификатором , а A:: является определителем вложенного имени .
  • A::B::F является квалифицированным идентификатором , и оба B:: и A::B:: являются спецификаторами вложенных имен .
  • ::A::B::F является квалифицированными -id и оба B:: и A::B:: являются спецификаторами вложенных имен .

[1] Это довольно неточное описание.Трудно описать грамматику простым английским языком ...

6 голосов
/ 05 ноября 2010

Вложенный спецификатор пространства имен:

nested-name-specifier :
    class-or-namespace-name::nested-name-specifier(optional)

То есть непустой список пространств имен и имен классов, за которыми следует каждое ::, представляющее относительное ветвление в общем «дереве пространства имен»программа.Например, my_namespace::, my_namespace::inner_namespace::, my_namespace::my_class:: и my_class::.

Обратите особое внимание на отличие от:

qualified-namespace-specifier :
    ::(optional) nested-name-specifier(optional) class-or-namespace-name

В том, что спецификатор вложенного имени можетне может быть абсолютным (с префиксом :: для ссылки на глобальную область), тогда как спецификатор квалифицированного пространства имен может быть, но не заканчивается на ::.

В вашем примере ::Sразрешается в функции ::S(), а не в структуре (правила приоритета для этого обсуждались здесь в Stackoverflow в вопросе, с которым вы связались в начале вашего вопроса), поэтому он не является вложенным спецификатором имени.

3 голосов
/ 05 ноября 2010

Хороший вопрос! Я узнал что-то новое, исследуя и экспериментируя на этом.

Вы правы в своем комментарии, ::S(); //Is ::S a nested name specifier <-- Yes, Indeed!

Вы оцените это, когда начнете создавать пространства имен. Переменные могут иметь одинаковые имена в пространствах имен, и оператор :: - это то, что их отличает. Пространства имен похожи на классы в некотором смысле, еще один уровень абстракции. Я бы не хотел утомлять вас пространствами имен. Возможно, вы не оцените спецификатор вложенного имени в этом примере ... рассмотрите этот:

#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;
}

Обратите внимание, что я использовал ::count, где я мог просто использовать count. ::count относится к глобальному пространству имен.

Так что в вашем случае, так как S () находится в глобальном пространстве имен (то есть он объявлен в том же файле или включенном файле или любом фрагменте кода, где он не заключен в namespace <name_of_namespace> { }, вы можете использовать new struct ::S или new struct S; в зависимости от того, что вы предпочитаете.

Я только что узнал об этом, поскольку мне было любопытно ответить на этот вопрос, поэтому, если у вас есть более конкретный и выученный ответ, пожалуйста, поделитесь :)

...