Это справочное руководство описывает язык программирования С++ по состоянии на май 1991. С++ - язык программирования общего назначения, базирующийся на языке программирования С Ь.
Ь "The C Programming Language" B. Kernighan, D. Ritchie. Prentice
В дополнение к возможностям С язык С++ предоставляет классы, функции подстановки, перегрузку операций, перегрузку имен функций, постоянные типы, ссылки, операторы управления свободной памятью, проверку параметров функций и приведение типов. Все расширения С суммируются в $$R.18.1. Различия между С++ и ANSI C++ приведены в $$R.18.2 Ь.
Ь American National Standard X3.159-1989. Американский национальный
Расширения С++ версии 1985 года до данного описания суммируются в $$R.18.1.2. Разделы, относящиеся к шаблонам типа ($$R.14) и управлению особыми ситуациями ($$R.15), являются местами планируемых расширений языка.
Это руководство содержит следующее: 1. Введение. 2. Соглашения о лексических понятиях. 3. Основные понятия. 4. Стандартные преобразования. 5. Выражения. 6. Операторы. 7. Описания. 8. Описатели. 9. Классы. 10. Производные классы. 11. Контроль доступа к членам. 12. Специальные функции-члены. 13. Перегрузка. 14. Шаблоны типов. 15. Управление особыми ситуациями. 16. Препроцессорная обработка.
В записи синтаксиса языка в этом руководстве синтаксические понятия обозначаются курсивом, а литеральные слова и символы шрифтом постоянной ширины. Варианты перечисляются на отдельных строках, за исключением тех немногих случаев, когда длинный список вариантов дается на одной строке с пометкой "один из". Необязательный терминальный или нетерминальный символ обозначается с помощью нижнего индекса "opt", поэтому
означает необязательное выражение, заключенное в фигурные скобки.
Программа на С++ состоит из одного или нескольких файлов ($$R.3.3). С логической точки зрения файл транслируется за несколько проходов. Первый проход состоит в препроцессорной обработке ($$R.16), на которой происходит включение файлов и макроподстановка. Работа препроцессора управляется с помощью команд, являющихся строками, первый символ которых отличный от пробела есть # ($$R2.1). Результат работы препроцессора есть последовательность лексем. Такую последовательность лексем, т.е. файл после препроцессорной обработки, называют единицей трансляции.
Существуют лексемы пяти видов: идентификаторы, служебные слова, литералы, операции и различные разделители. Пробелы, вертикальная и горизонтальная табуляция, конец строки, перевод строки и комментарии (все вместе "обобщенные" пробелы), как указано ниже, игнорируются, за исключением того, что они отделяют лексемы. Обобщенные пробелы нужны, чтобы разделить стоящие рядом идентификаторы, служебные слова и константы.
Комментарии Символы /* начинают комментарий, который завершается символами */. Такие комментарии не могут быть вложенными. Символы // начинают комментарий, который завершается концом этой строки. Символы //, /* и */ не имеют специального назначения в комментарии // и рассматриваются как обычные символы. Аналогично символы // и /* не имеют специального назначения внутри комментария /*.
Идентификатор - это последовательность букв и цифр произвольной длины. Первый символ должен быть буквой, символ подчеркивания _ считается буквой. Прописные и строчные буквы различаются. Все символы существенны.
Перечисленные ниже идентификаторы фиксируются как служебные слова и в другом смысле не могут использоваться:
В дополнение к этому идентификаторы, содержащие двойное подчеркивание (__) резервируются для реализаций С++ и стандартных библиотек и пользователи не должны употреблять их.
а следующие комбинации символов используются для задания операций:
Каждая операция считается отдельной лексемой.
Эти файлы являются частью ANSI стандарта для С. Кроме того заголовочные файлы
определяют типы самых важных библиотечных функций. Два последних файла входят в ANSI стандарт для С, файл <new.h> относится только к С++.
Есть несколько видов литералов (часто называемых "константами").
Все целые константы, состоящие из последовательности цифр, считаются десятичными (основание счисления десять), если только они не начинаются с 0 (цифра ноль). Последовательность цифр, начинающаяся с 0, считается восьмеричным целым (основание счисления восемь). Цифры 8 и 9 не являются восьмеричными. Последовательность цифр, начинающаяся с 0x или 0X, считается шестнадцатеричным целым (основание счисления шестнадцать). Шестандцатеричные цифры могут состоять из символов от a или A до f или F с десятичными значениями их от десяти до пятнадцати. Например, число двенадцать можно записать как 12, 014 или 0XC.
Символьной константой является один или несколько символов, заключенные в одиночные кавычки, например 'x'. Константа из одного символа имеет тип char. Значение константы из одного символа есть порядковый номер символа в таблице кодировки символов на данной машине. Символьные константы из нескольких символов имеют тип int. Значение такой константы зависит от реализации.
Если за обратной дробной чертой следует символ, отличный от перечисленных, результат неопределен. Комбинация \ooo состоит из обратной дробной черты, а которой следуют одна, две или три восьмеричные цифры. Считается, что они определяют значение искомого символа. Комбинация \xhhh состоит из из обратной дробной черты, за которой следует x, а за ним, в свою очередь, следует последовательность шестнадцатеричных цифр. Считается, что она задает значение искомого символа. Нет ограничения на длину этой последовательности шестнадцатеричных цифр. Последовательность восьмеричных или шестнадцатеричных цифр оканчивается, когда встречается первый символ, который не есть восьмеричная или шестнадцатеричная цифра соответственно. Если значение символьной константы превосходит максимальное из char, то оно определяется реализацией.
Константы с плавающей точкой состоят из целой части, символа точка, дробной части, e или E, целого показателя с возможным знаком и возможным окончанием, указывающим тип. Целая и дробная части состоят из последовательности десятичных (основание счисления десять) цифр. Или целая часть, или дробная часть (но не обе) могут отсутствовать. Или точка, или символ e (или E) вместе с показателем могут отсутствовать (но не оба). Тип константы с плавающей точкой есть double, если только он не задан явно с помощью окончания. Окончания f или F задают тип float, окончания l или L задают тип long double.
Строка литералов есть последовательность символов (как они определены в $$R.2.5.2), заключенная в двойные кавычки, т.е. "...". Строка имеет тип "массив символов" и класс памяти static ($$R.3.5), она инициализируется заданными символами. Будут ли все строки различны (т.е. хранится в отдельных объектах), определяется реализацией.
строка будет содержать два символа '\xA' и 'B' (а не один шестнадцатеричный символ '\xAB').
Имя обозначает объект, функцию, множество функций, элемент перечисления, тип, член класса, шаблон типа, значение или метку. Имя становится известно в программе с помощью описания. Имя можно использовать только в пределах части программы, называемой областью видимости имени. Имя имеет тип, который задает его использование. Имя, используемое в более чем одной единице трансляции, может обозначать один и тот же (а может и разные) объект, функцию, тип, шаблон типа или значение, в зависимости от компоновки ($$R.3.3) этих единиц трансляции.
Описание ($$r.7) делает известным в программе одно или несколько имен. Описание считается определением, если только оно не описывает функцию без задания ее тела ($$R.8.3), не содержит описателя extern ($$R.7.11), не имеет части инициализации или тела функции, не является описанием статического члена данных в описании класса ($$R.9.4), не является описанием имени класса ($$R.9.1), не является описанием typedef ($$R.7.1.3). Ниже приведены примеры определений:
тогда как ниже следуют только описания:
Существует четыре области видимости: локальная, функция, файл и класс.
Здесь второе x инициализируется своим собственным (неопределенным) значением.
Здесь элемент перечисления x опять инициализируется своим собственным (неопределенным) значением.
Программа состоит из одного или нескольких файлов, связываемых вместе ($$R.2). Файл состоит из последовательности описаний.
Программа должна содержать функцию с именем main(). Ей приписывается роль начала программы. Эта функция не является предопределенной для транслятора, она не может быть перегружена, а ее тип зависит от реализации. Предполагается, что любая реализация должна допускать два приведенных ниже определения и что можно добавлять после argv любые параметры. Функция main может определяться так
или
В последнем определении argc задает число параметров, передаваемых программе окружением, в котором она выполняется. Если argc не равно нулю, параметры должны передаваться как строки, завершающиеся символом '\0', с помощью argv[0] до argv[argc-1], причем argv[0] должно быть именем, под которым программа была запущена, или "". Должно гарантироваться, что argv[argc]==0.
описанной в <stdlib.h>, завершает программу. Значение параметра передается окружению программы в качестве результата программы.
описанной в <stdlib.h>, завершает программу без выполнения деструкторов статических объектов и без вызова функций, заданных в atexit().
Существует два описываемых класса памяти: автоматический и статический.
Существуют два вида типов: основные и производные.
Существует несколько основных типов. В стандартном заголовочном файле <limits.h> задаются в зависимости от реализации минимальные и максимальные значения каждого типа.
Существует потенциально бесконечное число производных типов, которые строятся из основных типов следующими способами:
Основные и производные типы можно поименовать с помощью механизма typedef ($$R.7.1.3), а семейство типов и функций можно задать и поименовать с помощью механизма шаблона типов ($$R.14).
Любой объект - это некоторая область памяти, адрес - выражение, ссылающееся на объект или функцию. Очевидным примером адреса будет имя объекта. Существуют операции, порождающие адреса, например, если E выражение типа указатель, то *E - адресное выражение, соответствующее объекту, на который указывает E. Термин "адрес" ("lvalue" т.е. left value - левая величина) появляется из оператора присваивания E1 = E2, где левый операнд E1 должен "адресовать" изменяемую переменную. При обсуждении всех операций в $$R.5 указывается применимы ли они к адресным операндам и порождают ли они сами адреса. Адрес может изменяться, если он не является именем функции, именем массива или const.
Некоторые операции в зависимости от своих операндов могут вызвать преобразование значения операнда от одного типа к другому. Здесь описываются преобразования, вызванные самыми обычными операциями, и объясняется каковы могут быть результаты таких преобразований. По мере надобности будут даны дополнительные объяснения при обсуждении каждой операции. Подобные преобразования также происходят при инициализации ($$R.8.4, $$R.8.4.3, $$R.12.8, $$R.12.1). В $$R.12.3 и $$R.13.2 описываются преобразования, заданные пользователем, и их соотношения со стандартными преобразованиями. В результате преобразования может получиться адрес, только если результат есть ссылка ($$R.8.2.2).
Всюду, где требуется целое, можно использовать char, short int, элемент перечисления ($$R.7.2) или битовое поле ($$R.9.6), причем в знаковом и беззнаковом вариантах. Если int может представлять все значения исходного типа, значение преобразуется к int, иначе оно преобразуется к unsigned int. Это называется стандартным преобразованием для целочисленных.
Если целое преобразуется в беззнаковый тип, то полученное значение есть наименьшее беззнаковое целое, совпадающее с целым со знаком по (mod 2**n), где n есть число битов в представлении беззнакового целого. Для представления в дополнительном коде это преобразование лишь концептуальное, никаких изменений в двоичном представлении в действительности не происходит.\
Для выражений типа float может использоваться арифметика с обычной точностью. Если значение с плавающей точкой меньшей точности преобразуется в значение типа float равной или большей точности, то изменения значения не происходит. Если значение с плавающей точкой большей точности преобразуется в значение типа float меньшей точности и значение находится в пределах, задаваемых представлением типа, то в результате может получиться или ближайшее большее или ближайшее меньшее представимое значение. Если результат оказался вне границ представления типа, поведение неопределено.
Преобразование значения с плавающей точкой к целочисленному типу сводится к "усечению", т.е. отбрасыванию дробной части. Такие преобразования зависят от машины, в частности в какую сторону будет проходить усечение для отрицательных чисел определяется на разных машинах по разному. Результат считается неопределенным, если значение нельзя представить в целочисленном типе.
Для большинства операций преобразования операндов и тип результата определяются одними и и теми же правилами. Это правило можно назвать "обычными арифметическими преобразованиями".
Всюду, где указатели ($$R.8.2.1) присваиваются, инициализируются, сравниваются или используются иным образом, могут происходить следующие преобразования:
Всюду, где ссылки ($$R.8.2.2) инициализируются (включая передачу параметров ($$R.5.2.2) и возврат значения функции ($$R.6.6.3)) или используются иным образом, возможны следующие преобразования:
Всюду, где указатели на члены ($$R.8.2.3) инициализируются, присваиваются, сравниваются или используются иным образом, могут происходить следующие преобразования:
Здесь определяются синтаксис, порядок вычисления и назначение выражений. Выражение - это последовательность операций и операндов, которая задает вычисление. Вычисление может выдавать в качестве результата значение и может вызывать побочные эффекты.
Первичными выражениями являются литералы, имена и имена, определенные с помощью операции разрешения области видимости ::.
Понятие уточняющее-имя-класса, за которым следует :: и имя члена этого класса ($$R.9.2), или члена базового по отношению к данному класса ($$R.10) является уточненное-имя. Его тип есть тип члена, а результат выражения есть этот член. Результат является адресом, если таковым является член. Имя класса может быть скрыто другим именем (не типа), в таком случае все равно имя класса доступно и его можно использовать. Если используется имя-класса::имя-класса или имя-класса::~имя-класса, оба понятия имя-класса должны обозначать один и тот же класс. С помощью такой записи обозначаются конструкторы ($$R.12.1) и деструкторы ($$R.12.4) соответственно. Можно использовать уточняющие имена неоднократно, например, N1::N2::N3::n, чтобы обозначать вложенные типы ($$R.9.7).
Постфиксное выражение, за которым следует выражение в квадратных скобках, является постфиксным выражением. Интуитивный смысл его индексирование. Первое из выражений должно иметь тип "указатель на T", а второе быть целочисленного типа. Тип результата есть "T". Выражение E1[E2] совпадает (по определению) с выражением *((E1) + (E2)). Подробности операций * и + даны в $$R.5.3 и $$R.5.7, а массивы обсуждаются в $$R.8.2.4.
Вызов функции является постфиксным выражением, за которым следует, возможно пустой, список выражений в скобках, разделенных запятой. Эти выражения образуют фактические параметры функции. Постфиксное выражение должно иметь тип "функция, возвращающая T", "указатель на функцию, возвращающую T" или "ссылка на функцию, возвращающую T", а результат операции вызова имеет тип "T".
Конструкция имя-простого-типа ($$R.7.1.6), за которой следует список-выражений в скобках образует значение указанного типа с учетом списка выражений. Если список выражений содержит более одного значения, тип должен быть классом с конструктором, описанным соответствующим образом ($$R.8.4, $$R.12.1).
Постфиксное выражение, за которым следует точка (.) и имя, является постфиксным выражением. Первое выражение должно быть объектом типа класс, а имя должно быть именем члена этого класса. Результатом будет поименованный член объекта и он будет адресом, если член является адресом.