- •И. А. Андрианов, д. В. Кочкин, с. Ю. Ржеуцкая
- •Учебное пособие
- •Оглавление
- •1. Основы языка 8
- •1.2.2 Простые типы данных 13
- •2. Работа с памятью 73
- •3. Основы объектно-ориентированного программирования 87
- •4.Обработка исключений 114
- •5. Шаблонные функции и классы. Библиотека стандартных шаблонов 130
- •6. Паттерны проектирования 159
- •7. Антипаттерны 211
- •9. Методы отладки и оптимизации кода 242
- •1. Основы языка
- •1.1.2 Понятие проекта
- •1.2 Простые типы данных
- •1.2.1 Понятие типа
- •1.2.2 Простые типы данных
- •1.2.3 Внутреннее представление простых типов
- •1.2.4 Ключевое слово typedef. Тип size_t
- •1.3 Константы и переменные
- •1.3.1 Литералы
- •1. Числовые константы:
- •2. Символьные константы:
- •1.3.2 Переменные
- •1.3.3 Описание переменных
- •1.4. Выражения. Преобразование типов
- •1.4.1 Операнды и операции
- •1.4.2 Приоритет операций
- •1.4.3 Преобразование типов
- •1.5 Ветвления и циклы
- •1.5.2 Циклы
- •1.6 Массивы, строки
- •1.6.1 Основные понятия
- •1.6.2 Встроенные массивы
- •1.6.3 Cтроки. Обработка строк с завершающим нулём
- •1.7 Указатели и ссылки. Связь указателей и массивов. Библиотека cstring
- •1.7.1 Понятия указателя и ссылки
- •1.7.2 Связь между массивами и указателями
- •1.7.3 Библиотека cstring
- •1.8 Использование типов vector и string
- •1.8.1 Шаблонный класс vector
- •1.8.2 Класс string
- •1.9 Структуры и объединения. Битовые поля
- •1.10.1 Понятие функции
- •1.10.2 Описание функции и прототип функции
- •1.11 Параметры функции. Способы передачи параметров
- •1.11.1 Параметры функции и глобальные переменные
- •1.11.2 Способы передачи параметров в функцию
- •1.11.3 Передача массивов в функцию
- •1.11.4 Параметры-константы
- •1.11.5 Значения параметров по умолчанию
- •1.12.1 Указатель на функцию
- •1.12.2 Функции с переменным числом параметров
- •1.12.3 Перегрузка функций
- •1.12.4 Встроенные (inline) функции
- •1.13 Рекурсивные функции
- •1.14 Пространства имён
- •1.15 Директивы препроцессора. Макросы
- •2. Работа с памятью
- •2.1 Управление выделением и освобождением памяти
- •2.1.1 Статическое и динамическое выделение памяти
- •2.1.2 Способы динамического выделения и освобождения памяти
- •2.2 Динамические структуры данных
- •2.2.1 Основные понятия
- •2.2.2 Примеры реализации динамических структур на основе указателей
- •3. Основы объектно-ориентированного программирования
- •3.1 Основные понятия ооп
- •3.2.1 Описание класса
- •3.2.2 Область видимости элементов класса. Инкапсуляция
- •3.2.3 Первые примеры
- •3.3. Конструкторы и деструкторы.
- •3.4 Указатель this
- •3.5 Перегрузка операций
- •3.6 Дружественные функции и классы
- •3.7 Статические элементы класса
- •3.8 Наследование и полиморфизм
- •3.8.1. Основные понятия
- •3.8.2 Одиночное наследование
- •3.8.3 Множественное наследование
- •3.8.4 Конструкторы и деструкторы классов-потомков
- •3.9. Полиморфизм при наследовании классов
- •3.9.1 Механизмы раннего и позднего связывания
- •3.9.2 Абстрактные классы
- •4.Обработка исключений
- •4.1 Основные понятия
- •4.2 Перехват исключений
- •4.3 Поиск обработчика исключений. Раскрутка стека.
- •4.4 Повторное возбуждение исключений
- •4.5 "Аппаратные" и "программные" исключения
- •4.6 Стандартные классы исключений
- •4.7 Спецификация исключений, возбуждаемых функцией
- •4.8 Исключения в конструкторах при наследовании
- •4.9. Исключения в деструкторах
- •5. Шаблонные функции и классы. Библиотека стандартных шаблонов
- •5.1 Шаблонные функции
- •5.2 Шаблонные классы
- •5.3 Специализация шаблонов
- •5.4 Шаблонные параметры шаблонов
- •5.5 Разработка шаблонных классов с настраиваемой функциональностью
- •5.6 Использование шаблонов для вычислений на этапе компиляции
- •5.7 Библиотека стандартных шаблонов (stl) – основные понятия
- •5.8 Последовательные контейнеры. Итераторы
- •5.9. Адаптеры контейнеров
- •5.10 Ассоциативные контейнеры
- •5.11 Алгоритмы
- •6. Паттерны проектирования
- •6.1 Порождающие шаблоны
- •6.2 Структурные шаблоны
- •6.3 Шаблоны поведения
- •6.4 Шаблон "фабричный метод" (Factory method)
- •6.5 Шаблон "одиночка" (Singleton)
- •6.6 Шаблон "итератор" (Iterator)
- •6.7 Шаблон "наблюдатель" (Observer)
- •6.8 Шаблон "пул объектов" (Object pool)
- •6.9 Шаблон "команда" (Command)
- •6. 10 Шаблон "посетитель" (Visitor)
- •6.11 Дополнительные задания
- •6.11.1 Шаблон Iterator
- •6.11.2 Шаблон Observer
- •6.11.3 Шаблоны Command и Observer
- •6.11.5 Шаблон Visitor
- •6.11.5 Разработка класса − контейнера
- •6.11.6 Оценка производительности кода
- •7. Антипаттерны
- •7.1 Программирование методом копирования и вставки (Copy-Paste Programming)
- •7.2 Спагетти-код (Spaghetti code)
- •7.3 Магические числа (Magic numbers)
- •7.4 Бездумное комментирование
- •7.5 Жесткое кодирование (Hard code)
- •7.6 Мягкое кодирование (Soft code)
- •7.7 Золотой молоток (Golden hammer)
- •7.8 Слепая вера (Blind faith)
- •7.9 Ненужная сложность (Accidental complexity)
- •7.10 Божественный объект (God Object)
- •7.11 Лодочный якорь (Boat anchor)
- •7.12 Поток лавы (Lava flow)
- •7.13 Изобретение велосипеда (Reinventing the wheel)
- •7.14 Программирование перебором (Programming by permutation)
- •8.1 Выведение типов
- •8.2 Списки инициализации
- •8.3 Улучшение процесса инициализации объектов
- •8.4 Цикл for по коллекции
- •8.5 Лямбда-функции
- •8.6 Константа нулевого указателя nullptr
- •8.7 "Умные" указатели
- •9. Методы отладки и оптимизации кода
- •9.1 Отладка кода
- •9.1.1 Основные этапы отладки
- •9.1.2 Инструменты и приёмы отладки
- •9.2 Оптимизация кода
- •9.2.1 Рекомендации по выполнению оптимизации
- •9.2.2 Методики оптимизации кода
- •Заключение
- •Библиографический список
1.4. Выражения. Преобразование типов
Выражения являются составной частью всех основных операторов С++, кроме того, имеется отдельный оператор-выражение для выполнения вычислений и присваиваний. Он представляет собой выражение с завершающей точкой с запятой.
1.4.1 Операнды и операции
Выражение состоит из операндов, знаков операций и, при необходимости, круглых скобок для изменения порядка выполнения операций. Операнды, в свою очередь, тоже являются выражениями, в частном случае, операндом может быть переменная, константа или результат функции (определенной в программе или в стандартной библиотеке С++). Функции с типом void не могут быть операндами в выражении, для их вызова используется отдельный оператор-выражение.
Рассмотрим операции над простыми типами данных. Они могут быть унарными (требуется только один операнд), бинарными (два операнда) и даже тернарными (три операнда).
Арифметические операции:
+ (плюс – унарный и бинарный)
- (минус – унарный и бинарный)
* (умножение)
/ (деление)
Следует заметить, что целое деление дает целый результат, при этом дробная часть усекается: 8 / 3 есть 2. Над целыми может выполняться операция % получения остатка: 11 % 4 равно 3, а 1 % 4 равно 1 (1 / 4 равно 0).
Логические операции:
&& (логическое И)
|| (логическое ИЛИ)
! (логическое НЕ – унарная операция)
В языке C++ логические операции могут быть применены ко всем целочисленным типам, а не только к типу bool. При этом все нулевые значения трактуются как false, а значения, отличные от нуля, – true.
Поразрядные логические операции применяются к целочисленным типам и выполняются для каждого бита отдельно по правилам булевой алгебры– при этом получается новое целочисленное значение.
& (поразрядная операция И). Например, 3 & 5 = 1 (в двоичной системе 011 & 101 = 001).
| (поразрядная ИЛИ). Например, 3 | 5 = 7.
^ (исключающее ИЛИ). Например, 3 ^ 5 = 6.
<< (сдвиг операнда влево на заданное число разрядов). Например, 3 << 2 = 12.
>> (сдвиг операнда вправо на заданное число разрядов). Например, 3 >> 1 = 1.
Операции сравнения:
== (два подряд идущих знака равно – сравнение на равенство)
!= (не равно)
< (меньше)
> (больше)
<= (меньше или равно)
>= (больше или равно)
В C++ есть операция присваивания =, а не оператор присваивания, как в некоторых других языках, например, Pascal. Операция не только присваивает значение справа левому операнду, но и возвращает это значение. Таким образом, присваивание может встречаться в неожиданном контексте; например, x=3*(a=2*x); - в результате новое значение получит не только переменная x, но и переменная a (однако, не рекомендуется злоупотреблять подобными конструкциями). Выражение a=b=c; означает присвоение c сначала переменной b, а затем переменной a.
Другим свойством операции присваивания является то, что она может совмещаться с большинством бинарных операций – получаются составные операции: +=, -=, *=, /=, %=
Например, выражение x+=2 равносильно x=x+2.
Операция запятая (‘,’) – операция последовательного вычисления. Вычисляет значение левого и правого операнда, при этом возвращает значение правого операнда. Например:
c=(a=8,9);
В a будет помешено значение 8, в c – значение 9 (не рекомендуем использовать подобные конструкции). Заметим, что если вы имели в виду число 8.9, но случайно поставили запятую вместо точки, то сообщения об ошибке не будет выведено.
Операции -- и ++ - декремент и инкремент – уменьшают или увеличивают значение аргумента на 1. Могут быть записаны как перед операндом (префиксная форма), так и после операнда (постфиксная форма). Если знак операции записан перед операндом, то изменение операнда происходит до его использования в выражении, если после операнда – после его использования. Например:
x=3; a=++x; //a=4, x=4
x=3; a=x++; //a=3, x=4
Ещё пример:
x=3; a=++x+ ++x; //a=10, x=5
В данном примере x увеличивается на единицу два раза, после чего вычисляется выражение. Последний пример плохо понимается, поэтому так писать не рекомендуется.
Операция sizeof(объект) – возвращает размер в байтах того объекта, к которому применяется (объектом может быть тип или переменная ).
В большинстве программ на C++ широко применяются указатели. Указатель – это переменная, содержащая адрес другой переменной. Унарная операция * разыменовывает указатель, т.е. *p есть объект, на который указывает p. Эта операция также называется косвенной адресацией. Например, если имеется объявление char* p, то *p есть символ, на который указывает p. Операция, противоположная разыменованию – получение адреса (&).Об указателях в C++ мы ещё поговорим подробнее.
В языке C++ имеется одна тернарная операция (с тремя аргументами) – условная операция, которая имеет следующий формат:
операнд1 ? операнд2 : операнд3
Операнд1 в данной операции задаёт условие. Если имеет значение true, то результатом операции будет являться значение операнда 2, иначе – операнда 3. Например, x=(a>0)?1:-1; - переменная x получит значение 1 или -1 в зависимости от значения переменной a. В данном примере скобки, в которые заключается условие, не являются обязательными, но с ними текст получается более наглядным.
