Выбрать главу

Если инициализатор для ссылки на тип T является адресом типа T или типом, производным от T (§R.10), для которого T служит доступным базовым типом (§R.4.6), ссылка будет обозначать значение, заданное инициализатором. Иначе, в том и только том случае, когда ссылка обозначает объект со спецификацией const, будет создан объект типа T и проинициализирован значением, заданным инициализатором.

Теперь ссылка играет роль имени этого объекта, например,

double d = 1.0;

double& rd = d; // rd ссылается на `d'

const double& rcd = d; // rcd ссылается на `d'

double& rd2 = 1; // ошибка: несоответствие типа

const double& rcd2 = 1; // rcd2 ссылается на временный объект

 // со значением `1'

Ссылку на volatile T можно инициализировать объектом типа volatile T или просто T, но не const T. Ссылку на const T можно инициализировать const T, просто T или чем-то, что можно преобразовать в тип T, но не volatile T. Ссылку на тип T (без const или volatile) можно инициализировать только объектом типа T.

Время жизни временного объекта, созданного при описанной инициализации, определяется текущей областью видимости, в которой он был создан (§R.3.5). Отметим, что ссылку на класс B можно инициализировать объектом класса D при условии, что В является однозначно определенным и доступным базовым классом для D (тогда говорят, что "D есть B"), см. §R.4.7.

R.9 классы

Класс есть тип. Его имя используется как имя-класса (§R.9.1), т.е. становится зарезервированным словом в его области видимости.

имя-класса:

 идентификатор

Для образования конструкции имя-класса используются спецификации-класса и спецификации-сложного-типа (§R.7.1.6). Объект класса состоит из последовательности (возможно пустой) членов.

спецификация-класса:

 заголовок-класса {список-членов opt}

заголовок-класса:

 служебное-слово-класса идентификатор opt спец-базовых opt

 служебное-слово-класса имя-класса спец-базовых opt

служебное-слово-класса:

 class

 struct

 union

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

Объекты пустого класса имеют ненулевой размер.

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

Структурой называется класс, описанный со служебным-словом-класса struct; ее члены и базовые классы (§R.10) считаются общими по определению (§R.11). Объединением называется класс, описанный со служебным-словом-класса union; его члены считаются общими по определению, и в любой момент времени объединение содержит только один член (§R.9.5).

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()

 //…

}

Конструкция спецификация-сложного-типа вместе со служебным-словом-класса, но без описания объекта или функции также может служить для задания имени класса, как и описание класса, однако в этом случае класс не считается определенным, например: