- •И. А. Андрианов, д. В. Кочкин, с. Ю. Ржеуцкая
- •Учебное пособие
- •Оглавление
- •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 Методики оптимизации кода
- •Заключение
- •Библиографический список
9. Методы отладки и оптимизации кода 242
9.1 Отладка кода 242
9.1.1 Основные этапы отладки 242
9.1.2 Инструменты и приёмы отладки 244
9.2 Оптимизация кода 255
9.2.1 Рекомендации по выполнению оптимизации 256
9.2.2 Методики оптимизации кода 257
ЗАКЛЮЧЕНИЕ 274
БИБЛИОГРАФИЧЕСКИЙ СПИСОК 275
ВВЕДЕНИЕ
Пособие предназначено для студентов нескольких IT-направлений, которые хотят хорошо освоить программирование на языке С++. Текст пособия базируется на большом количестве современных источников (они приведены в списке литературы), а также на собственном опыте авторов программирования на С++ и преподавания этого языка.
Работать с пособием могут студенты, имеющие различный уровень начальной подготовки. Если язык изучается "с нуля", рекомендуется очень внимательно проработать первые три главы пособия, которые содержат все начальные знания, необходимые для понимания остальных глав. Если у студента уже имеется некоторый опыт программирования на С++, советуем всё же прочитать первые три главы для устранения возможных пробелов в знаниях, после чего сосредоточить внимание на проработке оставшихся глав, которые посвящены таким аспектам программирования на С++, которые могут вызвать трудности при их освоении.
При изложении языковых конструкций С++ авторы сознательно отказались от таких строгих форм описания, как синтаксические диаграммы или формы Бэкуса-Наура. Возможные упрощения в формальном описании конструкций компенсируется большим количеством примеров и словесными пояснениями. Тем не менее, мы используем квадратные скобки для обозначения необязательных элементов описания языковой конструкции, а также символ "|", который обозначает ИЛИ. Это стандартные способы, которые используются в большинстве учебников по программированию.
Примеры, приведённые в пособии, протестированы с использованием Visual C++ 2013 и g++ 4.9.2 (mingw). Если возникают проблемы с их работоспособностью, возможной причиной может быть то, что в компиляторе не включена поддержка стандарта C++11. Например, в среде CodeBlocks данная настройка включается в меню "Project − Build Options", вкладки "Compiler Settings − Compiler Flags", параметр "Have g++ follow the C++ 11…". В среде Dev-Cpp нужно зайти в "Сервис − Параметры компилятора" и в поле "Компилятор" дописать ключ -std=c++11. В Visual Studio поддержка C++11 включена по умолчанию.
Напомним, что полноценное освоение материала пособия возможно только при активной практике программирования и большой настойчивости со стороны студента.
1. Основы языка
1.1 Программа на С++
1.1.1 Этапы обработки программы на С++
Для того, чтобы лучше понять структуру программы, рассмотрим основные этапы её обработки, предшествующие исполнению.
Этап 1. Препроцессинг (предобработка) – предварительная обработка текста программы с целью приведения его к виду, удобному для последующей компиляции. Правила препроцессорной обработки задаются в программе при помощи директив препроцессора. Директивы препроцессора начинаются с символа "#", многие из них располагаются в самом начале текста программы. Одной из наиболее востребованных является директива подключения к программе библиотек, входящих в состав стандартной библиотеки языка С++ (таких библиотек – несколько десятков, они содержат множество стандартных функций, переменных, классов, доступных для использования в любой программе на С++):
#include <имя_библиотеки>
В этом случае препроцессор добавляет в начало программы (вместо директивы #include) заголовочный файл подключаемой библиотеки, содержащий всю информацию, которая нужна компилятору для работы с этой библиотекой.
Этап 2. Компиляция – если программа не содержит синтаксических ошибок, то на этом этапе компилятор (compiler) формирует так называемый объектный код. Объектный файл содержит машинный код, ещё не готовый к выполнению, так как в нём содержатся ссылки на объекты (функции, переменные), расположенные в других объектных файлах и библиотеках. Имеется несколько форматов объектных файлов, вследствие этого объектные файлы и библиотеки, созданные разными компиляторами, могут быть несовместимы.
Этап 3. Компоновка (редактирование связей, линковка) - на этом этапе разрешаются все внешние связи (к программе подключаются все стандартные функции из библиотек, все части программы, возможно, размещённые в различных файлах, собираются воедино, при этом настраиваются конкретные адреса памяти для переменных). В результате формируется исполняемый код программы – единственный файл (в Windows он имеет расширение .exe – сокращение от executable). Для выполнения этапа компоновки используется программа-компоновщик (Linker).
