Справочное руководство по 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. Такое "трюкачество" с именами может вызвать недоумение, и лучше его избегать.