Прямое объявление внутри класса (не вложенного класса)

#c #forward-declaration

#c #прямое объявление

Вопрос:

Я наткнулся на это странное прямое объявление (или что-то в этом роде), где вместо обычного:

 class A;
class B{
    A* var;
}
  

Вы можете сделать

 class B{
   class A* var;
}
  

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

У кого-нибудь есть представление об этом? допустимо ли это прямое замедление?

пример: https://youtu.be/EIptJ0YrYg0?t=412

Комментарии:

1. Взгляните на разработанный спецификатор типа

Ответ №1:

Обратите внимание, что в документе говорится:

Обратите внимание, что новое имя класса также может быть введено с помощью разработанного спецификатора типа, который появляется как часть другого объявления, но только в том случае, если поиск по имени не может найти ранее объявленный класс с таким же именем.

Таким образом, если класс B заключен в пространство имен и предыдущее прямое объявление A не выполняется, то оно ссылается на n2::A то, что должно быть определено.

Комментарии:

1. Нет, это не B::A

2. @StoryTeller-UnslanderMonica Ок. Речь идет только о том, чтобы охватить пространство имен?

3. Нет, область действия блока также играет здесь роль. Если вы находитесь внутри блока в функции, это приведет к появлению локального класса.

Ответ №2:

Теперь это может быть детализированный спецификатор типа, но я не уверен в этом.

Это так. Фактически, class A; это объявление использует сложный спецификатор класса.

но я боюсь, что это может вызвать проблемы с областью видимости, о которых я в настоящее время не знаю

Единственный момент, связанный с областью видимости, о котором вам следует знать, это то, что если при первом обращении к классу используется сложный спецификатор типа (который сам по себе не является объявлением), поведение такое же, как если бы вы ввели прямое объявление в ближайшее пространство имен или область блока. Так, например

 namespace N {
  class foo {
     class bar {
       void func(class baz*);
     };
  };
};
  

… совпадает с

 namespace N {
  class baz;
  class foo {
     class bar {
       void func(baz*);
     };
  };
};
  

Ответ №3:

Да, это допустимое прямое объявление. Это называется сложным спецификатором типа.

Цитирую разработанный спецификатор типа из cppreference.

Если поиск по имени не находит ранее объявленного имени типа, детализированный спецификатор типа вводится с помощью class, struct или union (т. Е. не с помощью enum), а class-name является неквалифицированным идентификатором, тогда детализированный спецификатор типа является объявлением класса с именем класса.

Его также можно использовать для ссылки на уже объявленный класс, даже если его имя скрыто объявлением, отличным от типа.