Описание класса порождает новый тип. Например, ниже описываютсятри переменные трех различных типов: 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.