- •И. А. Андрианов, д. В. Кочкин, с. Ю. Ржеуцкая
- •Учебное пособие
- •Оглавление
- •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.8.2 Класс string
Обрабатывать строки, используя класс string, пожалуй, проще и удобнее, чем использовать встроенные строки с завершающим нулём.
Для ввода переменных этого типа можно использовать функцию getline.
getline(cin, s);
Здесь s — имя вводимой переменной типа string.
При описании переменной типа string можно сразу её инициализировать.
Например: string v("Hello");
Доступ к элементам строки типа string осуществляется стандартным образом через индекс. Над строками типа string определены следующие операции:
присваивания, например s1=s2;
объединения строк (s1+=s2 или s1=s1+s2) — добавляет к строке s1 строку s2, результат сохранится в строке s1;
сравнения строк на основе лексикографического порядка: s1=s2, s1!=s2, s1<s2, s1>s2, s1<=s2, s1>=s2 — результатом будет логическое значение;
При обработке строк типа string можно использовать следующие методы (методов у класса string много, поэтому здесь представлены, на наш взгляд, используемые наиболее часто). Пусть s – произвольная строка, тогда к каждому из методов обращаемся так:
s.имя_метода(параметры,_если_есть).
substr(pos, length) — возвращает подстроку из строки s, начиная с позиции pos длиной length символов;
empty() — возвращает значение true, если строка s пуста, false — в противном случае;
size(), length() – количество символов в строке (длина строки);
insert(pos, s1) — вставляет строку s1 в строку s, начиная с позиции pos;
erase(pos, length) — удаляет из строки s подстроку длиной length символов, начиная с позиции pos ;
find(s1, pos) — возвращает номер первого вхождения строки s1 в строку s, поиск начинается с номера pos, параметр pos может отсутствовать , в этом случае поиск идет с начала строки;
В качестве примера приведём последний (четвёртый!) вариант удаления пробелов из строки (примеры 1.7,1.8, 1.10). По лаконичности и наглядности текста, этот вариант, пожалуй, самый лучший. Но по эффективности безусловный лидер – вариант 1.8, в котором реализован собственный алгоритм обработки строки как массива символов.
//Пример 1.13 – удаление из строки пробелов
// с использованием типа string и его методов
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s; int n=0;
cout<<"?"; getline(cin, s);
while ((n=s.find(" "))>=0) s.erase(n,1);
cout << s << endl;
system("pause"); return 0;
}
1.9 Структуры и объединения. Битовые поля
Для полноты изложения основ языка С++ кратко коснёмся структур (struct) и объединений (union). Это сложные типы данных, определяемые разработчиком в программе, обычно, с целью повышения её наглядности и удобства разработки.
Важно отметить, что понятие структуры в языке С++ существенно расширено в соответствии с концепцией объектно-ориентированного программирования. В данном разделе в качестве введения рассмотрим структуры в стиле языка С, поскольку объектно-ориентированному программированию будет посвящена отдельная глава.
Структура – сложный тип данных, который объединяет под общим именем переменные любых типов (они называются полями структуры). Объявляется следующим образом:
struct [имя_типа_структуры]
{
описание поля 1;
описание поля 2;
….
} [переменные_типа_структуры];
Определение структуры завершается точкой с запятой.
Можно опустить имя_типа_структуры или переменные_типа_структуры, но не то и другое сразу. Если переменные типа структуры не объявлены сразу при описании структуры, значит, они будут объявлены где-нибудь позже отдельным оператором. При описании структуру можно инициализировать, как и массив (используя фигурные скобки).
Например:
struct student
{
char name[30]; // фамилия студента
unsigned int mark; // оценка по программированию
};
Мы создали новый тип student, который теперь можно использовать, как и любой другой тип данных. Например, можно создать переменные этого типа:
student x, y={"Попов", 5};//переменные x и y имеют тип student,
// переменная y инициализирована, а x – не инициализирована
Для обращения к элементам структуры используется операция ‘.’:
cout << y.name << " " << <<y.mark << "\n";
При работе со структурами часто используются указатели. Например:
student *py=&y; // указатель на объявленную ранее структуру y
Имеется отдельный синтаксис обращения к элементам структуры через указатель на структуру – использование операции ‘->’. Например:
cout << py->name << " " << <<py->mark << "\n";
Объединение – участок памяти, используемый несколькими разными переменными, которые могут быть различных типов. Объявляется с помощью ключевого слова union:
union [имя_типа_объединения]
{
объявление переменной 1;
объявление переменной 2;
….
} [переменные_объединения];
Например:
union int_char
{
int i;
char ch;
};
Как и для структур, объявлять переменные объединений можно как в конце оператора объявления объединения, так и отдельными операторами.
Доступ к элементам объединений осуществляется так же, как и к элементам структур, как показано в следующем примере:
// Пример 1.15 – выводим байты целого числа, используя union
union int_char
{
int i;
char ch[sizeof(int)];
};
int main(void)
{
int_char t;
t.i = 1;
for(int j=0;j<sizeof(int);j++)
cout << (int)t.ch[j]; //выводим значения отдельных байтов
}
Битовые поля. Язык C++ имеет удобные средства доступа к отдельны битам внутри байтов. Битовые поля могут быть объявлены только в структурах, объединениях и классах. Размер битового поля указывается через двоеточие при определении поля. Пример:
struct emp // структура сотрудник
{
char name[30];
unsigned lay_off: 1; //временно уволен или неактивен
unsigned hourly: 1; //почасовая оплата или оклад
unsigned deductions: 3; //вычеты
};
Здесь три последних поля хранятся в одном байте.
Ограничения на использование битовых полей:
нельзя получить адрес битового поля
нельзя создать битовое поле-массив
нельзя выходить за границы целого
1.10 Функции в С++ – основы
