- •Содержание
- •ВВЕДЕНИЕ
- •1.ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД
- •2. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
- •2.1. Абстрактные типы данных
- •2.2. Базовые принципы объектно-ориентированного программирования
- •2.3. Основные достоинства языка С++
- •2.4. Особенности языка С++
- •2.4.1. Ключевые слова
- •2.4.2. Константы и переменные
- •2.4.3. Операции
- •2.4.4. Типы данных
- •2.4.5. Передача аргументов функции по умолчанию
- •2.5.1. Объект cin
- •2.5.2. Объект cout
- •2.5.3. Манипуляторы
- •3.1. Объекты
- •3.2. Понятие класса
- •3.3. Конструктор копирования
- •3.4. Конструктор explicit
- •3.5. Указатель this
- •3.6. Встроенные функции (спецификатор inline)
- •3.7. Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •3.8. Вложенные классы
- •3.9. Static-члены (данные) класса
- •3.10. Компоненты-функции static и const
- •3.11. Proxi-классы
- •3.12. Ссылки
- •3.12.1. Параметры ссылки
- •3.12.2. Независимые ссылки
- •3.13. Пространства имен
- •3.13.3. Ключевое слово using как объявление
- •3.13.4. Псевдоним пространства имен
- •3.14. Практические приемы ограничения числа объектов класса
- •4. НАСЛЕДОВАНИЕ
- •4.1.1. Конструкторы и деструкторы при наследовании
- •4.2. Виртуальные функции
- •4.3. Абстрактные классы
- •4.4. Виртуальные деструкторы
- •4.6. Виртуальное наследование
- •5.2. Перегрузка операторов
- •5.2.2. Перегрузка унарного оператора
- •5.2.3. Дружественная функция operator
- •5.2.4. Особенности перегрузки операции =
- •5.2.5. Перегрузка оператора []
- •5.2.6. Перегрузка оператора ()
- •5.2.7. Перегрузка оператора ->
- •5.2.8. Перегрузка операторов new и delete
- •5.3. Преобразование типа
- •5.3.1. Явные преобразования типов
- •6. ШАБЛОНЫ
- •6.1. Параметризированные классы
- •6.2. Передача в шаблон класса дополнительных параметров
- •6.3. Шаблоны функций
- •6.4. Совместное использование шаблонов и наследования
- •6.5. Шаблоны класса и friend-функции
- •6.6. Некоторые примеры использования шаблона класса
- •6.6.1. Реализация smart-указателя
- •6.6.2. Задание значений параметров класса по умолчанию
- •7.2. Состояние потока
- •7.3. Строковые потоки
- •7.4. Организация работы с файлами
- •7.5. Организация файла последовательного доступа
- •7.6. Создание файла произвольного доступа
- •7.7. Основные функции классов ios, istream, ostream
- •8. ИСКЛЮЧЕНИЯ В С++
- •8.2. Перенаправление исключительных ситуаций
- •8.3. Исключительная ситуация, генерируемая оператором new
- •8.6. Спецификации исключительных ситуаций
- •8.7. Задание собственного неожиданного обработчика
- •9. СТАНДАРТНАЯ БИБЛИОТЕКА ШАБЛОНОВ (STL)
- •9.3. Категории итераторов
- •9.4. Операции с итераторами
- •9.5. Контейнеры последовательностей
- •9.5.2. Контейнер последовательностей list
- •9.5.3. Контейнер последовательностей deque
- •9.6. Ассоциативные контейнеры
- •9.6.1. Ассоциативный контейнер multiset
- •9.6.2. Ассоциативный контейнер set
- •9.6.3. Ассоциативный контейнер multimap
- •9.7.1. Адаптер stack
- •9.7.2. Адаптер queue
- •9.7.3. Адаптер priority_queue
- •9.8. Алгоритмы
- •9.8.1. Алгоритмы сортировки sort, partial_sort, sort_heap
- •9.8.2. Алгоритмы поиска find, find_if, find_end, binary_search
- •9.8.3. Алгоритмы fill, fill_n, generate и generate_n
- •9.8.4. Алгоритмы equal, mismatch и lexicographical_compare
- •9.8.6. Алгоритмы работы с множествами
- •9.8.7. Алгоритмы swap, iter_swap и swap_ranges
- •9.8.8. Алгоритмы copy, copy_backward, merge, unique и reverse
- •10. ПРИМЕРЫ РЕАЛИЗАЦИИ КОНТЕЙНЕРНЫХ КЛАССОВ
- •10.1. Связанные списки
- •10.1.1. Реализация односвязного списка
- •10.2. Реализация бинарного дерева
- •11. ПРОГРАММИРОВАНИЕ ДЛЯ WINDOWS
- •11.1. Система, управляемая сообщениями
- •11.2. Управление графическим выводом
- •11.3. Контекст устройства
- •11.3.1. Экран
- •11.3.2. Принтер
- •11.3.3. Объект в памяти
- •11.3.4. Информационный контекст
- •11.4. Архитектура, управляемая событиями
- •11.5. Исходный текст программы
- •11.7. Некоторые новые типы данных
- •11.8. Венгерская нотация
- •11.9. Точка входа программы
- •11.11. Создание окна
- •11.12. Цикл обработки сообщений
- •11.13. Оконная процедура
- •11.14. Обработка сообщений
- •11.15. Обработка сообщений функцией DefWindowProc
- •11.16. Синхронные и асинхронные сообщения
- •11.17. Еще один метод получения описателя контекста устройства
- •11.19. Полосы прокрутки
- •Литература
void advance (InputIterator& itr, Distance& n);
Вторая операция измеряет расстояние между итераторами first и second, возвращая полученное число через ссылку n:
void distance(InputIterator& first, InputIterator& second, Distance& n);
9.5. Контейнеры последовательностей
Стандартная библиотека С++ предоставляет три контейнера последова- тельностей – vector, list и deque. Первые два представляют собой классы, орга- низованные по типу массивов, а последний реализует связанный список. Класс vector является одним из наиболее популярных контейнерных классов в STL, динамически изменяющим свои размеры.
Использование контейнера vector наиболее эффективно при добавлении |
||
элементов в конец контейнера. Для приложений, выполняющихРчастые вставки |
||
|
|
У |
и удаления в конец и начало контейнера, более предпочтительным является |
||
deque. Если требуется выполнять вставки и удаление элементовИв любое место |
||
контейнера, то обычно используется list. |
|
|
Кроме перечисленных выше компонент-функций, общих для всех STL- |
||
контейнеров, контейнеры последовательностейГимеют несколько особых: front |
||
|
а |
|
и back − для возврата ссылки на первый и последний элемент в контейнере, |
||
push_back и pop_back – для встав и удБления последнего элемента контей- |
||
нера. |
ки |
|
|
|
|
9.5.1. Контейнер посл доват льностей vector |
||
Аналогично обычным массивам в С и С++, класс vector обеспечивает не- |
||
прерывную область памя и |
едля размещения данных. Следовательно, возможен |
|
о |
|
|
доступ к любому элемен у кон ейнера посредством индексации. В случае, если |
при добавлении новых элементьов в контейнер объема выделенной памяти недоста- точно, vector выделяет памя большего размера. Выполняется копирование ин- формации в выделенную бласть памяти и освобождение старой области памяти.
|
Контейнер vector поддерживает итераторы произвольного доступа, т.е. |
|
|
|
и |
все операции итераторов (табл. 4) могут быть применены к итератору контейне- |
||
ра vector. Все а горитмы STL могут работать с контейнером vector. |
||
|
л |
|
|
В приводимой ниже программе демонстрируется использование некото- |
|
|
б |
|
рых компонент-функций класса vector. |
||
и |
|
|
Б |
#include <iostream> |
|
using namespace std; |
#include <vector> template<class T>
void PrintVector(const std::vector<T> &vect); int main()
{std::vector<int> v,vv; PrintVector(v);
203
|
v.push_back(2); |
|
|
|
|
|
|
|
|
|||
|
v.push_back(5); |
|
|
|
|
|
|
|
|
|||
|
v.push_back(7); |
|
|
|
|
|
|
|
|
|||
|
v.push_back(1); |
|
|
|
|
|
|
|
|
|||
|
v.push_back(9); |
|
|
|
|
|
|
|
|
|||
|
v[4]=3; |
|
// изменить значение 5-го элемента на 3 |
|
|
|||||||
|
v.at(3)=6; |
|
// изменить значение 3-го элемента на 6 |
|
|
|||||||
|
try{ v.at(5)=0; |
|
// |
|
|
|
|
|
|
|
||
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
catch(std::out_of_range e){ //доступ к элементу вне массива (вектора) |
|||||||||||
|
} |
cout<<"\nИсключение : "<<e.what(); |
|
|
|
|
Р |
|||||
|
|
|
|
|
|
|
|
|
|
|
||
|
PrintVector(v); |
|
|
|
|
|
|
У |
||||
|
v.erase(v.begin() + 2); // удаление 3-го элемента (начальный индекс 0) |
|||||||||||
|
PrintVector(v); |
|
|
|
|
|
Г |
И |
||||
|
v.insert(v.begin() + 3,7);// добавление 7 после 3-го элемента вектора |
|||||||||||
|
PrintVector(v); |
|
|
|
|
|
|
|
|
|
||
|
vv.push_back(6); |
|
|
|
а |
|
|
|
||||
|
v.swap(vv); |
|
// замена массивов v и vv |
|
|
|
||||||
|
PrintVector(v); |
|
|
|
к |
Б |
|
|
|
|||
|
PrintVector(vv); |
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
||||
|
vv.erase(vv.begin()+1,vv.end()-2); //удаление со 2-го по n-2 элементов |
|||||||||||
|
PrintVector(vv); |
|
|
|
|
|
|
|
|
|||
|
vv.clear(); |
|
// чистка вс го в ктора |
|
|
|
|
|||||
|
PrintVector(vv); |
|
е |
|
|
|
|
|
||||
} |
return 0; |
|
|
т |
|
|
|
|
|
|
||
|
|
|
и |
|
|
|
|
|
|
|||
template<class T> |
|
|
|
|
|
|
||||||
void PrintVector(const оstd::vector<T> &vect) |
|
|
|
|
||||||||
{ std::vector<T>::const iterator pt; |
|
|
|
|
|
|
||||||
|
|
|
б |
|
|
|
|
|
|
|
|
|
|
if (vect.empty()) |
|
|
|
|
|
|
|
|
|||
|
|
и |
|
|
|
|
|
|
|
|
|
|
|
{ cout << endlл<< "Vector is empty." << endl; |
|
|
|
|
|||||||
|
|
return; |
|
|
|
|
|
|
|
|
|
|
Б |
|
|
|
|
|
|
|
|
|
|
||
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
cout<<"ВЕКТОР |
:" |
|
|
|
|
|
|
|
<<" Размер ="<<vect.size()
<<" вместимость ="<<vect.capacity()<<endl; cout<<"содержимое :"; for(pt=vect.begin();pt!=vect.end();pt++) cout<<*pt<<' ';
cout<<endl;
}
204
Инструкция std::vector<int> v,vv;
определяет два экземпляра класса v и vv для хранения int чисел. При этом соз- даются два пустых контейнера с нулевым числом элементов и нулевой вмести- мостью (числом элементов, которые могут быть сохранены в контейнере). Компонента-функция push_back(), имеющаяся во всех контейнерах последова- тельностей, используется для добавления элемента в контейнер v. Инструкции
v[4]=3;
v.at(3)=6;
[], возвращающей либо ссылку на значение в требуемой позицииР, либо кон- стантную ссылку на это значение, в зависимости от того, является ли контейнер
демонстрируют два способа индексирования контейнера vector (используются и
для контейнера deque). Первая инструкция реализуется перегрузкой операции
константным. Следующая функция at() выполняет тоУже, Иосуществляя дополни- тельно проверку на выход индекса из диапазонаГ. Функции size() и capacity() возвращают число элементов вектора (диапазон) и его вместимость. Вмести- мость удваивается каждый раз в том случаеБ, когда при попытке разместить оче- редной элемент в контейнере все выделенное пространство памяти занято.
При добавлении первого элемен размер стал равен 1, вместимость 1, второго – размер 2, вместимость 2, третьего − 3 и 4 соответственно, четвертого − 4 и 8 и т.д. В примере приведена внешняя функция просмотра вектора и его
размера и вместимости PrintVector(). Для прохода по вектору используется ите- |
|||
ратор pt: |
|
та |
|
|
к |
||
|
std::vector<T>::const |
||
|
iterator pt; |
||
|
Этот итератор (const |
iterator)едопускает считывание, но не модификацию |
|
элементов контейнера vector. При проходе по вектору используются функции |
|||
begin() и end(), д ступные для всех контейнеров первого класса. |
|||
|
Кроме переч сленныхтвыше в программе используются функции класса |
||
vector: clear(), empty()оswap(). |
|||
|
Контейнер vector не должен быть пустым, иначе результаты функций |
||
|
|
и |
|
front и back удут не определены. |
|||
|
|
л |
|
|
9.5.2. Контейнер последовательностей list |
||
|
б |
|
|
|
Контейнерный класс list реализуется как двусвязный список, что позволя- |
||
и |
|
|
|
Б |
|
|
|
ет ему поддерживать двунаправленные итераторы для прохождения контейнера как в прямом, так и в обратном направлениях. Для контейнера list может быть использован любой алгоритм, использующий однонаправленные и двунаправ- ленные итераторы. Контейнер последовательностей list эффективно реализует операции вставки и удаления в любое место контейнера.
Шаблон класса list предоставляет еще восемь функций-членов: splice, push_front, pop_front, remove, unique, merge, reverse и sort. Многие функции класса vector поддерживаются также и в классе list. Для работы с объектом (его компонентами) необходимо включать заголовочный файл <list>.
205
#include <iostream> |
|
|
|
|
|
|
|
||
using namespace std; |
|
|
|
|
|
|
|
||
#include <list> |
|
|
|
|
|
|
|
|
|
template<class T> |
|
|
|
|
|
|
|
|
|
void PrintList(const std::list<T> &lst); |
|
|
|
|
|||||
int main() |
|
|
|
|
|
|
|
|
|
{ std::list<int> |
ls,ll; |
|
|
|
|
|
|
|
|
std::list<int>::iterator itr; |
|
|
|
|
|
|
|
||
int ms[]={2,5,3}; |
|
|
|
|
|
|
|
Р |
|
int mm[]={2,15,23,1}; |
|
|
|
|
|
|
|||
ls.push_back(2); ls.push_front(5); |
|
|
|
|
|||||
ls.push_front(7); ls.push_back(9); |
|
|
|
|
|||||
PrintList(ls); |
|
|
|
|
|
|
У |
||
ll.insert(ll.begin(),ms,ms+sizeof(ms)/sizeof(int));// добавление |
И |
||||||||
PrintList(ll); |
|
|
|
|
|
Г |
|||
ll.push_front(6); |
|
|
|
|
|
|
|
|
|
ls.splice(ls.end(),ll); |
|
|
|
|
|
|
|
||
PrintList(ls); |
|
|
|
|
а |
|
|
|
|
PrintList(ll); |
|
|
|
|
|
Б |
|
|
|
ls.sort(); |
|
// сортировка ls |
к |
|
|
|
|||
PrintList(ls); |
|
|
|
|
|
|
|
|
|
|
|
еме |
|
|
|
|
|||
ll.insert(ll.begin(),mm,mm+sizeof(mm)/sizeof(int)); |
|
|
|
||||||
PrintList(ll); |
|
|
|
|
|
|
|
|
|
ll.sort(); |
|
// сортировка ll |
|
|
|
|
|
||
ls.merge(ll); |
|
// перенос эл |
|
|
н ов ll в ls |
|
|
|
|
PrintList(ls); |
|
|
|
|
|
|
|
|
|
ls.pop_front(); |
|
// удаление первого элемента списка |
|
|
|
||||
ls.pop_back(); |
|
и |
|
|
|
|
|
|
|
|
// удалениетпоследнего элемента списка |
|
|
||||||
ls.reverse(); |
|
// реверсивныйо |
переворот списка ls |
|
|
|
|||
PrintList(ls); |
|
|
|
|
|
|
|
|
|
б |
// удаление из списка ls одинаковых элементов |
|
|||||||
ls.unique(); |
|
|
|||||||
и |
|
|
|
|
|
|
|
|
|
PrintList(ls);л |
|
|
|
|
|
|
|
||
ls.swap(ll); |
|
// обмен содержимым списков ls и ll |
|
|
|
||||
Б |
|
|
|
|
|
|
|
|
|
PrintList(ls); |
|
|
|
|
|
|
|
|
|
PrintList(ll); |
|
|
|
|
|
|
|
|
|
ls.push_front(2); |
|
|
|
|
|
|
|
|
|
ls.assign(ll.begin(),ll.end());// замена ls содержимым ll |
|
|
|
||||||
PrintList(ls); |
|
|
|
|
|
|
|
|
|
PrintList(ll); |
|
|
|
|
|
|
|
|
|
ls.remove(2); |
|
// удаление из ls всех 2 |
|
|
|
|
|||
PrintList(ls); |
|
|
|
|
|
|
|
|
|
itr=ls.begin(); |
|
|
|
|
|
|
|
|
|
itr++; |
|
|
|
|
|
|
|
|
|
206
|
ls.erase(itr,ls.end());// удаление из ls элементов с itr до ls.end |
||||||||
|
PrintList(ls); |
|
|
|
|
|
|
||
|
return 0; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<class T> |
|
|
|
|
|
|
||
|
void PrintList(const std::list<T> &lst) |
|
|
|
|
||||
|
{ std::list<T>::const_iterator pt; |
|
|
|
|
||||
|
if (lst.empty()) |
|
|
|
|
|
|
||
|
{ cout << endl << "List is empty." << endl; |
|
|
|
|||||
|
return; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cout<<" LIST размер = "<<lst.size()<<" содержимое = "; |
||||||||
|
for(pt=lst.begin();pt!=lst.end();pt++) |
|
У |
Р |
|||||
|
cout<<*pt<<' '; |
|
|
Г |
И |
||||
|
cout<<endl; |
|
|
||||||
|
} |
|
|
|
|
Б |
|
|
|
|
Результат работы программы: |
|
|
|
|||||
|
|
|
|
|
|||||
|
LIST |
размер = 4 |
содержимое = 7 5 2 9 |
|
|
|
|||
|
LIST |
размер = 3 |
содержимое |
= 2 5 3 |
|
|
|
||
|
LIST |
размер = 8 |
содержимое |
= 7 5 2 9 6 2 5 3 |
|
|
|||
|
List is empty. |
|
сод ржимоеа= 2 2 3 5 5 6 7 9 |
|
|
||||
|
LIST |
размер = 8 |
|
|
|||||
|
LIST |
размер = 4 |
сод ржимоек |
= 2 15 23 1 |
|
|
|||
|
LIST |
|
|
т |
= 1 2 2 2 3 5 5 6 7 9 15 23 |
||||
|
размер = 12 сод ржимое |
||||||||
|
LIST |
размер = 10 содержимое |
= 15 9 7 6 5 5 3 2 2 2 |
|
|||||
|
LIST |
|
о |
содержимое |
= 15 9 7 6 5 3 2 |
|
|
||
|
размер = 7 |
|
|
||||||
|
|
и |
|
|
|
|
|
|
|
|
List is empty. |
|
|
|
|
|
|
||
|
LIST |
размер = 7 |
содержимое |
= 15 9 7 6 5 3 2 |
|
|
|||
|
л |
|
|
содержимое |
= 15 9 7 6 5 3 2 |
|
|
||
|
LIST |
размер = 7 |
|
|
|||||
|
б |
размер = 7 |
содержимое |
= 15 9 7 6 5 3 2 |
|
|
|||
|
LIST |
|
|
||||||
|
LIST |
размер = 6 |
содержимое |
= 15 9 7 6 5 3 |
|
|
|||
|
LIST |
размер = 1 |
содержимое |
= 15 |
|
|
|
||
Б |
Рассмотрим некоторые конструкции, использованные в программе. |
иИспользуя функцию push_back (общую для всех контейнеров последова- тельностей) вставки чисел в конец ls и push_front (определенную для классов list
и deque), добавления значений в начало ls, создаем последовательность целых чисел. В инструкции
ll.insert(ll.begin(),ms,ms+sizeof(ms)/sizeof(int));
используется функция insert класса list, вставляющая в начало последовательно- сти ll элементы массива ms.
Далее в строке ls.splice(ls.end(),ll);
207