R Справочное руководство по С++

R.9.1 Имена класса.

   


Назад  |  Вперёд

Описание класса порождает новый тип. Например, ниже описываются три переменные трех различных типов:

           struct X { int a; };
           struct Y { int a; };
           X a1;
           Y a2;
           int a3;

Отсюда следует, что такие присваивания приводят к несоответствию типов:

           a1 = a2;   // ошибка: Y присваивается X
           a1 = a3;   // ошибка: int присваивается X

Ниже описывается перегрузка ($$R.13) функции f(), а не просто повторное описание той же функции:

           int f(X);
           int f(Y);

По той же причине нельзя дважды определять класс, это видно из примера ниже, где дважды определен S:

           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. Такое "трюкачество" с именами может вызвать недоумение, и лучше его избегать. Конструкция имя-typedef ($$R.7.1.3) обозначает класс и считается именем-класса, см. также $$R.7.1.3.


Назад  |  Вперёд


OtDiatlovaOU
К началу книги

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.