
- •1. Введение
- •2. Элементы языка
- •2.1. Первые программы
- •2.2. Алфавит языка
- •2.3. Комментарии
- •2.4. Типы данных
- •2.5. Целые типы данных
- •2.6. Плавающие типы данных
- •2.7. Константы-строки, или литералы
- •2.8. Директива препроцессора define
- •2.9. Описания
- •2.10. Модификатор const
- •3. Выражения
- •3.1. Операция и выражение присваивания
- •3.2. Арифметические операции
- •3.3. Операции отношения
- •3.4. Логические операции
- •3.5. Побитовые операции
- •3.6. Сдвиги
- •?????3.8. Тернарная или условная операция
- •3.9. Операция следования
- •3.10. Приоритеты операций и порядок вычисления
- •4.6. Оператор выбора switch
- •4.7. Оператор цикла while
- •4.8. Цикл с постусловием do-while
- •4.9. Оператор for
- •4.10. Оператор безусловного перехода
- •4.11. Оператор break
- •4.12. Оператор continue
- •4.13. Оператор return
- •5. Указатели
- •5.1. Определение указателей
- •5.2. Указатели и массивы
- •5.3. Адресная арифметика
- •5.4. Символьные массивы и строки
- •5.5. Многомерные массивы
- •5.6. Указатели и многомерные массивы
- •6. Операция sizeof
- •7. Операции для работы с динамической памятью
- •7.1. Операция выделения памяти new
- •7.2. Операция освобождения памяти delete
- •8. Функции
- •8.1. Определение и вызов функции
- •8.2. Функции. Передача аргументов
- •8.3. Передача многомерных массивов
- •8.4. Указатели на функции
- •8.5. Ссылки
- •8.6. Ссылки в качестве параметров функций
- •8.7. Аргументы по умолчанию
- •8.8. Переопределение функций
- •8.9. Шаблоны функций
- •9. Объявления и определения
- •10. Область существования имени
- •11. Область видимости
- •Здесь будет напечатано
- •12. Классы памяти
- •13. Объявления объектов и типов
- •14. Имена типов
- •15. Синоним имени типа
- •16. Правила преобразования стандартных типов
- •16.1. Явные преобразования
- •16.2. Неявные преобразования стандартных базовых типов
- •16.3. Преобразование производных стандартных типов
- •17. Перечисления
- •18. Классы
- •18.1. Объявление классов
- •18.2. Конструкторы
- •18.3. Деструкторы
- •18.4. Статические члены класса
- •18.5. Указатель this
- •18.6. Статические функции-члены
- •18.7. Указатели на члены класса
- •18.8. Инициализация данных–членов класса
- •18.9. Конструктор копирования и операция присваивания
- •18.10. Дружественные функции
- •18.11. Конструктор и операция new
- •18.12. Вызов деструктора
- •19. Производные классы
- •19.1. Построение производного класса
- •19.2. Защищенные члены класса
- •19.3. Управление уровнем доступа к членам класса
- •19.4. Последовательность вызова конструктора и деструктора при построении производного класса на основе одного базового
- •19.5. Преобразования типов
- •20. Полиморфизм
- •20.1. Раннее и позднее связывание
- •20.2. Виртуальные функции
- •20.3. Абстрактные классы
- •21. Переопределение стандартных операций
- •21.1. Основные определения и свойства
- •21.2. Операции new и delete при работе с абстрактными типами
- •21.3. Использование new при создании динамического объекта абстрактного типа
- •21.4. Операция delete
- •21.5. Преобразование типов
- •22. Некоторые особенности переопределенных операций
- •22.2. Операция [ ]
- •23. Классы и шаблоны
- •24. Списки
- •24.1. Операции над односвязными списками
- •24.2. Двунаправленные и кольцевые списки
- •24.3. Операции над кольцевыми списками
- •25. Стеки
- •25.1. Реализация стека через массив
- •25.2. Реализация стека через динамическую цепочку звеньев
- •26. Двоичные деревья
- •26.1. Определение и построение
- •26.2.Таблицы
- •27. Список литературы
13. Объявления объектов и типов
При объявлениях можно использовать одновременно более одного модификатора (это * [ ] и ( ) ). Это даёт возможность создавать бесконечное множество сложных описателей типов. В то же время, некоторые комбинации недопустимы:
элементами массива не могут быть функции;
функции не могут возвращать массив или функцию.
При интерпретации сложных описателей квадратные и круглые скобки (справа от идентификатора) имеют приоритет перед * (слева от идентификатора). Квадратные или круглые скобки имеют один и тот же приоритет.
Спецификатор типа рассматривается на последнем шаге. Можно использовать круглые скобки, чтобы изменить порядок интерпретации на необходимый. Для правильной интерпретации сложных описателей можно придерживаться следующего правила («изнутри - наружу»).
Начать с идентификатора и посмотреть вправо, есть ли квадратные или круглые скобки.
Если они есть, то проинтерпретировать эту часть описателя и затем посмотреть налево в поиске *.
Если на любой стадии справа встретится закрывающая круглая скобка, то вначале необходимо применить все эти правила внутри круглых скобок, а затем продолжить интерпретацию.
Интерпретировать спецификатор типа.
Например, при использовании конструкции
int *(*array[10]) ( );
объявляется имя array как массив из 10 указателей на функцию без аргументов, возвращающую указатель на целое значение.
14. Имена типов
В некоторых конструкторах языка явно используются имена типов (операции sizeof, new, cast). Имя типа – это просто объявление объекта такого типа, в котором опущено имя самого объекта.
Примеры имён типов:
int - целое
double - плавающее с двойной точностью
int * - указатель на целое
int * [10] - массив указателей на целое
int(*)[10] - указатель на массив на 10 целых
int * (void) - функция без аргументов, возвращающая указатель на целое.
int (*) (void) - указатель на функцию без аргументов, возвращающую результат целого типа.
15. Синоним имени типа
Синоним имени типа строится при помощи ключевого слова typedef. Выражение, в котором присутствует это ключевое слово, является описанием некоторого имени. Наличие слова typedef говорит о том, что объявляемый идентификатор становится не именем объекта некоторого типа, а синонимом имени этого типа.
int INTEGER; // INTEGER - имя переменной типа int
typedef int INT; // INT – синоним типа int
typedef unsigned size_t;
typedef char string [255];
typedef void (*FPTR) (int);
Последние две строки определяют string как синоним типа «строка из 255 символов», а FPTR – синоним типа «указатель на функцию, имеющую один аргумент типа int и не возвращающую никакого результата.»
После объявления с помощью typedef новое имя становится полноценным именем типа:
string array; // array – массив из 255 символов
FPTR func_pointer; // void (*func_pointer)(int);
typedef string STRING;
Использование typedef может упростить понимание сложных имен типов. Так, тип int (*(void))[ ] можно построить так:
typedef int intarray[]; // тип «массив целых»
typedef intarray * ptrtointarray; //тип указателя на массив целых
typedef ptrtointarray TYPE (void);
Теперь имя TYPE можно использовать, например, в прототипах:
double fun (int, int, TYPE);