Вопрос

$ 10,2 / 4- "[ Примечание:Поиск имени в детализированный спецификатор типа (3.4.4) или базовый спецификатор (пункт 10), например, игнорирует все объявления, не относящиеся к типу , при поиске имени в спецификаторе вложенного имени (3.4.3) игнорирует объявления функций, переменных и перечислителя."

Я обнаружил, что это утверждение очень сбивает с толку в этом разделе при описании поиска по имени.

void S(){}

struct S{
   S(){cout << 1;}
   void f(){}
   static const int x = 0;
}; 

int main(){ 
   struct S *p = new struct ::S;  // here ::S refers to type
   p->::S::f();

   S::x;  // base specifier, ignores the function declaration 'S'

   ::S(); // nested name specifier, ignores the struct declaration 'S'.
   delete p;
} 

Мои вопросы:

  1. Правильно ли я понимаю правила?

  2. Почему ::S в строке doing new автоматически обрабатывается значение struct S, тогда как в последней строке ::S означает функции S в глобальном пространстве имен.

  3. Указывает ли это на двусмысленность в документации, или это еще один день для меня, чтобы держаться подальше от стандартного документа C ++?

Это было полезно?

Решение

Q1: я так думаю.

Q2: совместимость с C. Когда вы объявляете struct В C имя тега именно то, что имя тега. Чтобы иметь возможность использовать его автономным способом, вам нужен typedef. Отказ В C ++ вам не нужен Typedef, который облегчает проще. Но правила C ++ были осложнены необходимостью иметь возможность импортировать уже существующие заголовки C, которые «перегружены» имя тега с именем функции. Канонический пример этого является UNIX stat() Функция, которая использует struct stat* как аргумент.

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

Другие советы

Вы ошибаетесь насчет второго комментария.В S::x, тот самый S является именем во вложенном спецификаторе имени.То, на что Стандарт ссылается с помощью "base-specifier", заключается в следующем

namespace B { struct X { }; void X() }
struct A : B::X { }; // B::X is a base-specifier

Вы также не правы на этот счет:

::S(); // спецификатор вложенного имени, игнорирует объявление структуры 'S'.`

Этот код вызывает функцию не потому, что ::S был бы спецификатором вложенного имени (это не спецификатор вложенного имени!), А потому, что имена функций скрывают имена классов или перечислений, если и функция, и класс / перечисление объявлены в одной области видимости.

FWIW, следующий код был бы в равной степени действителен для строки 2 вашего основного

p->S::f();

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top