Справочное руководство по C++ | страница 54
>struct S { int a; };
>struct S { int a; }; // ошибка, повторное определение
Описание класса включает имя класса в ту область видимости, внутри которой оно произошло, и закрывает любой класс, объект, функцию или другое описание этого имени в объемлющей области видимости (§R.3.2). Если имя класса описано в такой области видимости, где уже был описан объект с таким же именем, функция или элемент перечисления, то обращаться к классу можно только с помощью конструкции спецификация-сложного-типа (§R.7.1.6), например:
>struct stat {
> //…
>};
>stat gstt; // просто `stat' используется для
> // определения переменной
>int stat(struct stat*); // переопределение `stat' как функции
>void f()
>{
> struct stat* ps; // нужен префикс struct
> // для задания структуры stat
> //…
> stat(ps); // вызов stat()
> //…
>}
Конструкция спецификация-сложного-типа вместе со служебным-словом-класса, но без описания объекта или функции также может служить для задания имени класса, как и описание класса, однако в этом случае класс не считается определенным, например:
>struct s { int a; };
>void g()
>{
> struct s; // скрывает глобальную структуру `s'
> s* p; // используется локальная структура `s'
> struct s { char* p; }; // описание локальной структуры `s'
>}
Такие правила позволяют классам ссылаться друг на друга при их описании, пример,
>class vector;
>class matrix {
> //…
> friend vector operator*(matrix&, vector&);
>};
>class vector {
> //…
> friend vector operator*(matrix&, vector&);
>};
Описание friend (дружественные функции) обсуждается в §R.11.4, а функция operator в §R.13.4. Если класс, указанный как друг, пока еще не описан, его имя считается принадлежащим той же области видимости, в которой находится имя класса, содержащего описание friend (§R.11.4).
В описании объектов или функций можно также использовать конструкцию спецификация-сложного-типа (§R.7.1.6). Ее использование отличается от описания класса тем, что если класс, чье имя указано в спецификации, находится в текущей области видимости, то имя из этой спецификации будет ссылаться на него, например:
>struct s { int a; }
>void g()
>{
> struct* s p = new s; // обращение к глобальной `s'
> p-›a = 1;
>}
Имя считается описанным сразу же после появления его идентификатора в описании. Отсюда следует, что в описании
>class A * A;
A в начале задается, как имя класса, а затем оно переопределяется как имя указателя на объект этого класса, поэтому для обозначения этого класса следует использовать спецификацию-сложного типа class A. Такое "трюкачество" с именами может вызвать недоумение, и лучше его избегать.