Мюррей Хилл - C++ Страница 52
Мюррей Хилл - C++ читать онлайн бесплатно
f (a,(t=3,t+2),c)
имеет три параметра, вторым из которых является значение 5.
7.16 Перегруженные Операции
Большинство операций может быть перегружено, то есть, описано так, чтобы они получали в качестве операндов объекты классов (см. #8.5.11). Изменить приоритет операций невозмоно. Невозможно изменить смысл операций при применении их к неклассовым объектам. Предопределенный смысл операций = и amp; (унарной) при применении их к объектам классов может быть именен.
Эквивалентность операций, применяемых к основным типам (например, ++a эквивалентно a+=1), не обязательно выполняется для операций, применяемых к классовым типам. Некоторые оперции, например, присваивание, в случае применения к основным типам требуют, чтобы операнд был lvalue; это не требуется для операций, описанных для классовых типов.
7.16.1 Унарные Операции
Унарная операция, префиксная или постфиксная, может быть определена или с помощью функции члена (см. #8.5.4), не получающей параметров, или с помощью функции друга (см. #8.5.10), получающей один параметр, но не двумя способами одновременно. Так, для любой унарной операции @, [email protected] и @x могут интерпретроваться как x.операция@() или операция@(x). При перегрузке операций ++ и – невозможно различить префиксное и постфикное использование.
7.16.2 Бинарные Операции
Бинарная операция может быть определена или с помощью функции члена (см. #8.5.4), получающей один параметр, или с помощью функции друга (см. #8.5.9), получающей два параметра, но не двумя способами одновременно. Так, для любой бинарной операции @, [email protected] может быть проинтерпретировано как x.operator @(y) или [email protected](x,y).
7.16.3 Особые Операции
Вызов функции первичное_выражение ( список_выражений opt )
и индексирование
первичное_выражение [ выражение ]
считаются бинарными операциями. Именами определяющей функции являются соответсвенно operator() и operator[]. Обрщение x(arg) интерпретируется как x.operator()(arg) для класового объекта x. Индексирование x[y] интерпретируется как x. operator[](y).
8. Описания
Описания используются для определения интерпретации, дваемой каждому идентификатору. Они не обязательно резервируют память, связанную с идентификатором. Описания имеют вид:
описание: спецификаторы_описания opt список_описателей opt ; описание_имени asm_описание
Описатели в списке_описателей содержат идентификаторы, подлежащие описанию. Спецификаторы_описания могут быть опущны только в определениях внешних функций (#10) или в описанях внешних функций. Список описателей может быть пустым толко при описании класса (#8.5) или перечисления (#8.10), то есть, когда спецификаторы_описания – это class_спецификатор или enum_спецификатор. Описания имен описываются в #8.8; опсания asm описаны в #8.11.
спецификатор_описания: спецификатор_класса_памяти спецификатор_типа спецификатор_функции friend typedef
спецификаторы_описания: спецификатор_описания спецификатор_описания opt
Список должен быть внутренне непротиворечив в описывамом ниже смысле.
8.1 Спецификаторы Класса Памяти
Спецификаторы – это:
спецификатор_класса_памяти: auto static extern register
Описания, использующие спецификаторы auto, static и register также служат определениями тем, что они вызывают рзервирование соответствующего объема памяти. Если описание extern не является определением (#4.2), то где-то еще должно быть определение для данных идентификаторов.
Описание register лучше всего представить как описание auto (автоматический) с подсказкой компилятору, что описанные переменные усиленно используются. Подсказка может быть проинорирована. К ним не может применяться операция получения ареса amp;.
Спецификаторы auto или register могут применяться только к именам, описанным в блоке, или к формальным параметрам. Внутри блока не может быть описаний ни статических функций, ни статических формальных параметров.
В описании может быть задан максимум один sc_спецификтор. Если в описании отсутсвует спецификатор_класса_памяти, то класс памяти принимается автоматическим внутри функции и статическим вне. Исключение: функции не могут быть автоматческими.
Спецификаторы static и extern могут использоваться толко для имен объектов и функций.
Некоторые спецификаторы могут использоваться только в описаниях функций:
спецификатор_функции: overload inline virtual
Спецификатор перегрузки overload делает возможным ипользование одного имени для обозначения нескольких функций, см. #8.9.
Спецификатор inline является только подсказкой компилтору, не влияет на смысл программы и может быть проигнорирван. Он используется, чтобы указать на то, что при вызове функции inline-подстановка тела функции предпочтительнее обычной реализацци вызова функции. Функция (#8.5.2 и #8.5.10), определенная внутри описания класса, является inline по умолчанию.
Спецификатор virtual может использоваться только в опсаниях членов класса, см. #8.5.4.
Спецификатор friend используется для отмены правил сорытия имени для членов класса и может использоваться только внутри описаний классов, см. #8.5.9.
С помощью спецификатора typedef вводится имя для типа, см. #8.8.
8.2 Спецификаторы Типа
Спецификаторами типов (спецификатор_типа) являются:
спецификатор_типа:
простое_имя_типа спецификатор_класса enum-спецификатор сложный_спецификатор_типа const
Слово const можно добавлять к любому допустимому спецфикатору_типа. В остальных случаях в описании может быть дано не более одного спецификатора_типа. Объект типа const не яляется lvalue. Если в описании опущен спецификатор типа, он принимается int.
простое_имя_типа: char short int long unsigned float double const void
Слова long, short и unsigned можно рассматривать как прилагательные. Они могут применяться к типу int; unsigned может также применяться к типам char, short и long.
Спецификаторы класса и перечисления обсуждаются в #8.5 и #8.10 соответственно.
сложный_спецификатор_типа: ключ typedef-имя ключ идентификатор
ключ: class struct union enum
Сложный спецификатор типа можно использовать для ссылки на имя класса или перечисления там, где имя может быть скрыто локальным именем. Например:
class x (* ... *);
void f(int x) (* class x a; // ... *)
Если имя класса или перечисления ранее описано не было, сложный_спецификатор_типа работает как описание_имени, см. #8.8.
8.3 Описатели
Список_описателей, появляющийся в описании, есть раздленная запятыми последовательность описателей, каждый из кторых может иметь инициализатор.
список_описателей: иниц_описатель иниц_описатель , список_описателей
иниц_описатель:
описатель инициализатор opt
Инициализаторы обсуждаются в #8.6. Спецификатор в описнии указывает тип и класс памяти объектов, к которым относятся описатели. Описатели имеют синтаксис:
описатель: оп_имя ( описатель ) * const opt описатель amp; const opt описатель описатель ( список_описаний_параметров ) описатель [ константное_выражение opt ]
оп-имя: простое_оп_имя typedef-имя :: простое_оп_имя
простое_оп_имя: идентификатор typedef-имя ~ typedef-имя имя_функции_операции имя_функции_преобразования
Группировка та же, что и в выражениях.
8.4 Смысл описателей
Каждый описатель считается утверждением того, что если в выражении возникает конструкция, имеющаяя ту же форму, что и описатель, то она дает объект указанного типа и класса памти. Каждый описатель содержит ровно одно оп_имя; оно опредляет описываемый идентификатор. За исключением описаний некторых специальных функций (см. #8.5.2) , оп_имя будет простым идентификатором.
Если в качестве описателя возникает ничем не снабженный идентификатор, то он имеет тип, указанный спецификатором, возглавляющим описание.
Описатель в скобках эквивалентен описателю без скобок, но связку сложных описателей скобки могут изменять.
Теперь представим себе описание
T D1
где T – спецификатор типа (как int и т.д.), а D1 – опсатель. Допустим, что это описание заставляет идентификатор иметь тип «... T», где «...» пусто, если идентификатор D1 есть просто обычый идентификатор (так что тип x в «int x» есть просто int). Тогда, если D1 имеет вид
*D
то тип содержащегося идентификатора есть «...указатель на T.»
Если D1 имеет вид
* const D
то тип содержащегося идентификатора есть «... констанный указатель на T», то есть, того же типа, что и *D, но не lvalue.
Если D1 имеет вид
amp;D
или
amp; const D
то тип содержащегося идентификатора есть «... ссылка на T.» Поскольку ссылка по определению не может быть lvalue, ипользование const излишне. Невозможно иметь ссылку на void (void amp;).
Если D1 имеет вид
D (список_описаний_параметров)
то содержащийся идентификатор имеет тип «... функция, принимающая параметр типа список_описаний_параметров и возращающая T.»
список_описаний_параметров: список_описаний_парам opt ... opt
список_описаний_парам: список_описаний_парам , описание_параметра описание_параметра
описание_параметра: спецификаторы_описания описатель спецификаторы_описания описатель = выражение спецификаторы_описания абстракт_описатель спецификаторы_описания абстракт_описатель = выражение
Жалоба
Напишите нам, и мы в срочном порядке примем меры.