Бьярн Страустрап - Справочное руководство по C++
- Название:Справочное руководство по C++
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Бьярн Страустрап - Справочное руководство по C++ краткое содержание
Справочное руководство по C++ - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Описатели имеют такой синтаксис:
описатель:
имя-в-описателе
операция-ptr описатель
описатель ( список-описаний-параметров ) список-спецификаций-cv opt
описатель [ выражение-константа opt]
( описатель )
операция-ptr:
* список-спецификаций-cv opt
& список-спецификаций-cv opt
полное-имя-класса :: * список-спецификаций-cv opt
список-спецификаций-cv:
const
volatile
имя-в-описателе:
имя
имя-класса
~имя-класса
имя-typedef
уточненное-имя-типа
Конструкция имя-класса имеет определенное назначение при описании класса с этим именем, она же используется как уточнение в операции :: для разрешения коллизий в области видимости (§R.12.1, §R.12.4).
R.8.1 Имена типов
Имя типа необходимо указывать при задании операции явного преобразования типа или в качестве параметра в операциях sizeof или new. Для этого служит конструкция имя-типа, которая синтаксически эквивалентна описанию объекта или функции этого типа, в котором отсутствует имя объекта или функции.
имя-типа:
список-спецификаций-типа абстрактный-описатель opt
список-спецификаций-типа:
спецификация-типа список-спецификаций-типа
абстрактный-описатель:
операция-ptr абстрактный-описатель opt
абстрактный-описатель opt( список-описаний-параметров ) список-спецификаций cv opt
абстрактный-описатель opt[ выражение-константа opt]
( абстрактный-описатель )
Можно однозначно указать, в каком месте абстрактного-описателя нужно добавить идентификатор, чтобы конструкция стала описателем, допустимым в описании. Тогда поименованный тип будет тем же, что и тип гипотетического идентификатора. Например, описания
int // int i
int * // int *pi
int *[3] // int *p[3]
int (*)[3] // int (*p3i)[3]
int *() // int *f()
int (*)(double) // int (*pf)(double)
задают соответственно такие типы: "целое", "указатель на целое", "массив из 3 указателей на целое", "указатель на массив из 3 целых", "функция без параметров, возвращающая указатель на целое", "указатель на функцию с параметром типа double, возвращающую целое".
R.8.1.1 Устранение неоднозначности
Неоднозначность, отмеченная в §R.6.8, которая возникает из-за сходства между приведением, заданным в функциональном стиле, и описанием, может также появиться в контексте описания. В этом контексте она проявляется как сходство между описанием функции, в котором есть избыточные скобки вокруг имени параметра, и описанием объекта, в котором в качестве инициализатора используется операция приведения, заданная в функциональном стиле. Как и для операторов, неоднозначность устраняется правилом, согласно которому следует считать описанием любую конструкцию, которая может служить таковым. Можно явно устранить неоднозначность в описании или с помощью приведения, заданного не в функциональном стиле, или с помощью операции = для обозначения инициализации, например,
struct S {
S(int);
};
void foo(double a)
{
S x(int(a)); // описание функции
S y((int)a); // описание объекта
S z = int(a); // описание объекта
}
R.8.2 Смысл описателей
Список описателей следует после (возможно пустого) списка спецификаций-описания (§R.7.1). Каждый описатель содержит в точности одно имя-из-описателя, которое задает описываемый идентификатор. Если не считать описаний некоторых специальных функций (§R.12.3, §R.13.4), имя-из-описателя является просто идентификатором. Спецификации auto, static, extern, register, friend, inline, virtual или typedef относятся непосредственно к каждому имени-из-описателя из списка описателей. Тип каждого имени-из-описателя определяется как спецификацией-описания (§R.7.1), так и его описателем.
Таким образом, описание некоторого идентификатора имеет вид
T D
где T обозначает тип, а D - описатель. Если в описании D есть идентификатор без скобок, то тип этого идентификатора есть T.
В описании, где D имеет вид
( D1 )
тип D1 такой же, как и тип D. Наличие скобок не меняет типа заключенного в них имени-из-описателя, но для сложных описателей оно может повлиять на порядок применения операций.
R.8.2.1 Указатели
В описании T D, в котором D имеет вид
* список-спецификаций-cv optD1
тип описываемого идентификатора есть
"… список-спецификаций-cv указатель на T". Конструкция список-спецификаций-cv относится к указателю, а не к указуемому объекту.
Например, в описаниях
const ci = 10, *pc = &ci, *const cpc = pc;
int i *p, *const cp = &i;
определяются: ci как константа целое; pc как указатель на константу целое; cpc как константа указатель на константу целое; i как целое; p как указатель на целое; и cp как константа указатель на целое. После инициализации значения ci, cpc и cp не могут быть изменены. Значение pc можно изменять так же, как и значение объекта, на который указывает cp. Приведем примеры допустимых операций:
i = ci;
*cp = ci;
pc++;
pc = cpc;
pc = p;
Недопустимы следующие операции:
ci = 1; // ошибка
ci++; // ошибка
*pc = 2; // ошибка
cp = &ci; // ошибка
cpc++; // ошибка
p = pc; // ошибка
Каждая из этих операций недопустима или потому, что она изменяет значение объекта, описанного со спецификацией const, или потому, что делает такое изменение возможным позднее с помощью указателя, настроенного на объект без спецификации const.
Аналогична ситуация со спецификацией volatile.
Обратитесь к §R.5.17 и §R.8.4.
Нельзя описывать указатели на ссылки (§R.8.2.2) или указатели на битовые поля (§R.9.6).
R.8.2.2 Ссылки
В описании T D, в котором D имеет вид
& список-спецификаций-cv optD1
тип описываемого идентификатора есть "…список-спецификаций-cv ссылка на T". Тип void& недопустим.
Например, во фрагменте
void f(double& a) { a += 3.14; }
//…
double d = 0;
f(d);
a описывается как параметр, являющийся ссылкой, поэтому вызов f(d) приведет к увеличению d на 3.14. Во фрагменте
int v[20];
//…
int& g(int i) { return v[i]; }
//…
g(3) = 7;
описывается: функция g() возвращает ссылку на целое; поэтому оператор g() = 7; присвоит 7 четвертому элементу массива v. Рассмотрим следующий программный фрагмент:
struct link {
link* next;
};
link* first;
void h(link*& p) // `p' ссылка на указатель
{
p-›next = first;
first = p;
p = 0;
}
void k()
{
link* q = new link;
h(q);
}
Здесь p описано как ссылка на указатель на link, поэтому вызов h(q) не изменит значение q, равное 0, см. также §R.8.4.3.
Читать дальшеИнтервал:
Закладка: