Мюррей Хилл - C++ Страница 58
Мюррей Хилл - C++ читать онлайн бесплатно
описатель_функции:
описатель ( список_описаний_параметров )
Если параметр специфицирован как register, то соответтвующий фактический параметр будет по возможности копироватся в регистр на входе в функцию. Если для параметра специфцировано константное выражение в качестве инициализатора, то это значение используется как значение параметра по умолчнию.
Тело функции имеет вид
тело_функции: составной_оператор
Вот простой пример полного определения функции:
int max(int a, int b, int c) (* int m = (a « b) ? a : b; return (m » c) ? m : c; *)
Здесь int – это спецификатор_типа; max(int a, int b, int c) – это описатель_функции; (* ... *) – это тело_функции.
Поскольку в контексте выражения имя моссива (в особености, как фактического параметра) принимается как означающее указатель на первый элемент массива, описания формальных праметров, которые описаны как «массив из ...», корректируются так, чтобы читались как «указатель на ...».
В определении конструктора могут быть заданы инициализторы для базового класса и для членов. Это главным образом полезно для объектов класса, констант и ссылок, где семантика инициализации и присваивания различаются. Инициализатор_базвого имеет вид
инициализатор_базового: : список_инициализаторов_членов
список_инициализаторов_членов: инициализатор_члена инициализатор_члена , список_инициализаторов_членов
инициализатор_члена: идентификатор opt ( список_параметров opt )
Если в инициализаторе_члена дан идентификатор, то список параметров используется для инициализации названного члена; если нет, то список параметров используется для базового класса. Например:
struct base (* base(int); ... *);
struct derived : base (* derived(int); base b; const c;
*);
derived::derived(int a) : (a+1), b(a+2), c(a+3) (* /* ... */ *)
derived d(10);
Сначала конструктор базового класса вызывается для обекта d с параметром 11, затем вызывается конструктор для члна b с параметром 12 и конструктор для члена c с параметром 13. Затем выполняется тело derived::derived() (см. #8.5.5). Порядок, в котором вызываются конструкторы для членов, не утановлен. Если базовый класс имеет конструктор, который можно вызывать без параметров, не надо давать никакой список парметров. Если класс члена имеет конструктор, который можно взывать без параметров, для этого члена не надо давать никакой список параметров.
11. Командные Строки Компилятора
Компилятор содержит препроцессор, способный выполнять макроподстановки, условную компиляцию и включение именованных файлов. Строки, начинающиеся с #, относятся к препроцессору. Эти строки имеют независимый от остального языка синтаксис; они могут появляться в любом месте и оказывать влияние, котрое распространяется (независимо от области видимости) до конца файла исходной программы.
Учтите, что определения const и inline дают альтернативы для большинства использований #define.
11.1 Замена Лексем
Командная строка компилятора вида
#define идентификатор строка_лексем вызывает замену препроцессором последующих вхождений идентификатора, заданного строкой символов. Точка с запятой внутри (или в конце) строки символов является частью этой строки.
Строка вида
#define идентификатор( идентификатор , ... , идентификатор) строка_лексем
где нет пробела между первым идентификатором и (, явлется макроопределением с параметрами. Последующие вхождения первого идентификатора с идущими за ним (, последователностью символов, разграниченной запятыми, и ), заменяются строкой символов, заданной в определении. Каждое местоположние идентификатора, замеченного в списке параметров определния, заменяется соответствующей строкой из вызова. Фактичекими параметрами вызова являются строки символов, разделенные запятыми; однако запятые в строке, заключенной в кавычки, или в круглых скобках не являются разделителями параметров. Число формальных и фактических параметров должно совпадать. Строки и символьные константы в символьной строке сканируются в писках формальных параметров, но строки и символьные константы в остальной программе не сканируются в поисках определенных
(с помощью define) идентификаторов.
В обоих случаях строка замещения еще раз сканируется в поисках других определнных идентификаторов. В обоих случаях длинное определение может быть продолжено на другой строке с помощью записи \ в конце продолжаемой строки.
Командная строка вида
#undef идентификатор
влечет отмену препроцессорного определения идентификатра.
11.2 Включение Файлов
Командная строка компилятора вида
#include «имя_файла»
вызывает замену этой строки полным содержимым файла имя_ файла. Сначала именованный файл ищется в директории первончального исходного файла, а затем в стандартных или заданных местах. Альтернативный вариант, командная строка вида
#include «имя_файла»
производит поиск только в стандартном или заданном мете, и не ищет в директории исходного файла. (То, как эти мета задаются, не является частью языка.) Включения с помощью #include могут быть вложенными.
11.3 Условная Компиляция
Командная строка компилятора вида
#if выражение
проверяет, является ли результатом вычисления выражения не-ноль. Выражение должно быть константным выражением, котрые обсуждаются в #12. Кроме обычных операций С++ может ипользоваться унарная операция defined. При применении к идетификатору она дает значение не-ноль, если этот идентификатор был ранее определен с помощью #define и после этого не было отмены определения с помощью #undef; иначе ее значение 0. Командная строка вида
#ifdef идентификатор
проверяет, определен ли идентификатор в препроцессоре в данный момент; то есть, был ли он объектом командной строки # define. Командная строка вида
#ifndef идентификатор
проверяет, является ли идентификатор неопределенным в препроцессоре в данный момент.
После каждого из трех видов может стоять произвольное количество строк, возможно, содержащих командную строку
#else
и далее до командной строки
#endif
Если проверенное условие истинно, то все строки между #else и #endif игнорируются. Если проверенное условие ложно, то все строки между проверкой и #else или, в случае отсуттвия #else, #endif, игнорируются.
Эти конструкции могут быть вложенными.
11.4 Управление Строкой
Для помощи другим препроцессорам, генерирующим программы на С++, строка вида
#line константа «имя_файла»
заставляет компилятор считать, например, в целях дианостики ошибок, что константа задает номер следущей строки исходного файла, и текущий входной файл именуется идентификтором. Если идентификатор отсутствует, то запомненное имя файла не изменяется.
12. Константные Выражения
В нескольких местах С++ требует выражения, вычисление которых дает константу: в качестве границ массива (#8.4), в case выражениях (#9.7), в качестве значений параметров фунции по умолчанию (#8.3), и в инициализаторах (#8.6). В первом случае выражение может включать только целые константы, сивольные константы, константы перечислений, значения несостаных const, инициализированных константными выражениями, и sizeof выражения, возможно, связанные бинарными операциями
+ – * / % amp; ! ^ «„ “» == != « » «= »= amp; amp; !!
или унарными операциями
+ – ~ !
или тернарной операцией
?:
Скобки могут использоваться для группирования, но не для вызова функций.
Во всех остальных случаях константное выражение может также содержать унарную операцию amp;, примененную к внешним или статическим объектам, или к внешним или статическим массивам, индексированным константным выражением. Унарная операция amp; может также быть применена неявно с помощью употребления ниндексированных массивов и функций. Основное правило состоит в том, что инициализаторы должны при вычислении давать контанту или адрес ранее описанного внешнего или статического обйекта плюс или минус константа.
Меньшая широта допустима для константных выражений после #if: недопустимы имена, описанные const, sizeof выражения и перечислимые константы.
13. Соображения Мобильности
Определенные части С++ являются машинно зависимыми по своей сути. Следующий ниже список мест возможных затруднений не претендует на полноту, но может указать на основные из них.
Как показала практика, характеристики аппаратуры в читом виде, такие, как размер слова, свойства плавающей арифмтики и целого деления, не создают особых проблем. Другие апаратные аспекты отражаются на различных программных разработках. Некоторые из них, особенно знаковое расширение (преобразование отрицательного символа в отрицательное целое) и порядок расположения байтов в слове, являются досадными пмехами, за которыми надо тщательно следить. Большинство отальных являются всего лишь мелкими сложностями.
Число регистровых переменных, которые фактически могут быть помещены в регистры, различается от машины к машине, как и множество дейсвующих типов. Тем не менее, все компиляторы на «своей» машине все делают правильно; избыточные или ндействующие описания register игнорируются.
Жалоба
Напишите нам, и мы в срочном порядке примем меры.