- •Содержание
- •ВВЕДЕНИЕ
- •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. Полосы прокрутки
- •Литература
6.ШАБЛОНЫ
6.1.Параметризированные классы
Параметризированный класс – некоторый шаблон, на основе которого можно строить другие классы. Этот класс можно рассматривать как некоторое описание множества классов, отличающихся только типами их данных. В С++ используется ключевое слово template для обеспечения параметрического по- лиморфизма. Параметрический полиморфизм позволяет использовать один и тот же код относительно различных типов (параметров тела кода). Это наиболее полезно при определении контейнерных классов. Шаблоны определения класса и шаблоны определения функции позволяют многократно использовать код,
корректно по отношению к различным типам, позволяя компилятору автомати- |
|||||
зировать процесс реализации типа. |
|
У |
Р |
||
Шаблон класса определяет правила построения каждого отдельного клас- |
|||||
|
|
Г |
И |
||
са из некоторого множества разрешенных классов. |
|
||||
Спецификация шаблона класса имеет вид: |
|
|
|
||
template <список параметров> |
Б |
|
|
|
|
|
|
|
|
||
class объявление класса |
лона |
|
|
|
|
|
|
|
|
||
Список параметров класса-ш б |
представляет собой идентификатор |
||||
|
к |
|
при его генерации. Иден- |
||
типа, подставляемого в объявление д нного класса |
|||||
тификатору типа предшеству |
лючевое слово class или typename. Рассмотрим |
пример шаблона класса работы с динамическим массивом и выполнением кон-
|
|
|
|
т |
|
троля за значениями индекса при обращении к его элементам. |
|||||
|
#include <iostream> |
ет |
|||
|
|
|
о |
|
|
|
using namespace std; |
|
|||
|
#include <string.h> |
|
|||
|
template <class T> |
// или иначе template <typename T> |
|||
|
|
л |
|
|
|
|
class vector |
|
|
|
|
|
б |
|
|
|
|
|
{ |
T *ms;и |
|
|
|
|
|
int size; |
|
|
|
и |
|
|
|
||
|
|
public: |
|
|
|
Б |
|
vector() : size(0),ms(NULL) {} |
|||
|
~vector(){delete [] ms;} |
||||
|
|
// уменьшение размера массива на 1 элемент
129
{ T *tmp = ms;
if(size>1) ms=new T[--size]; if(tmp)
{memcpy(ms,tmp,sizeof(T)*size); // перезапись без последнего
//элемента
increm – добавлен е в конец вектора нового элемента, dekrem – уменьшение числа элементов на единицу и операция [] обращения к i-му элементу вектора.
|
delete [] tmp; |
|
// удаление временного массива |
|
|
||||||
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T &operator[](int ind) |
// определение обычного метода |
|
|
|||||||
|
{ // if(ind<0 || (ind>=size)) throw IndexOutOfRange; // возбуждение |
||||||||||
|
|
|
|
|
|
// исключительной ситуации IndexOutOfRange |
|||||
|
return ms[ind]; |
|
|
|
|
|
|
|
Р |
||
}; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
И |
||
int main() |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
У |
|
|||
{ vector <int> VectInt; |
|
|
|
|
|
||||||
|
vector <double> VectDouble; |
|
|
|
|||||||
|
|
Г |
|
|
|||||||
|
VectInt. inkrem(3); |
|
|
|
|
|
|
||||
|
|
|
|
|
Б |
|
|
|
|||
|
VectInt. inkrem(26); |
|
|
|
|
|
|
|
|||
|
VectInt. inkrem(12); |
|
|
|
|
|
|
|
|||
|
|
// получен int-ве тор из 3 атрибутов |
|
||||||||
|
VectDouble. inkrem(1.2); |
|
|
|
|
|
|
||||
|
VectDouble. inkrem(.26);//получ н doubleа-вектор из 2 атрибутов |
|
|||||||||
|
int a=VectInt[1]; |
|
// a = ms[1] |
|
|
|
|
||||
|
cout << a << endl; |
|
|
|
к |
|
|
|
|
||
|
|
|
е |
|
|
|
|
||||
|
int b=VectInt[4]; |
|
|
|
|
|
|
||||
|
|
// буд возбуждена исключительная ситуация |
|||||||||
|
cout << b << endl; |
|
// но не обработана |
|
|
|
|
||||
|
double d=VectDouble[0]; |
ет |
|
|
|
|
|
||||
|
cout << d << endl; |
о |
|
|
|
|
|
||||
|
VectInt[0]=1; |
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
||
|
VectDouble[1]=2.41; |
|
|
|
|
|
|
|
|||
|
return 0; |
|
и |
|
|
|
|
|
|
|
|
} |
л |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|||
Класс vectorбнаряду с конструктором и деструктором имеет 2 функции: |
|||||||||||
|
и |
|
|
|
|
|
|
|
|
|
|
Б |
|
|
|
|
|
|
|
|
|
|
Параметр шаблона vector – любой тип, у которого определены операция присваивания и операция new. Например, при задании объекта типа vector <int> происходит генерация конкретного класса из шаблона и конструирование соот- ветствующего объекта VectInt, при этом тип Т получает значение типа int. Ге- нерация конкретного класса означает, что генерируются все его компоненты- функции, что может привести к существенному увеличению кода программы.
Выполнение функций
130
VectInt.increm(3);
VectInt.increm(26);
VectInt.increm(12);
приведет к созданию вектора (массива) из трех атрибутов (3, 26 и 12). Сгенерировать конкретный класс из шаблона можно, явно записав:
template vector<int>;
|
При этом не будет создано никаких объектов типа vector<int>, но будет |
|||||||||
сгенерирован класс со всеми его компонентами. |
|
Р |
||||||||
|
В некоторых случаях желательно описания некоторых компонент- |
|||||||||
функций шаблона класса выполнить вне тела шаблона, например: |
|
|||||||||
|
#include <iostream > |
|
|
|
|
|
|
|||
|
using namespace std; |
|
|
|
У |
|
|
|||
|
template <class T1,class T2> |
|
|
|
|
|||||
|
|
Г |
|
|
||||||
|
T1 sm1(T1 aa,T2 bb) |
|
// |
|
|
|||||
|
|
описание шаблонаИглобальной |
||||||||
|
{ return (T1)(aa+bb); |
|
// |
функции суммирования значений |
||||||
|
} |
|
|
|
|
// |
двух аргументов |
|
|
|
|
template <class T1,class T2> |
|
Б |
|
|
|
||||
|
class cls |
|
|
|
|
|
|
|
||
|
{ T1 a; |
|
|
|
а |
|
|
|
||
|
|
T2 b; |
|
|
|
|
|
|
||
|
public: |
|
|
е |
|
|
|
|
||
|
|
cls(T1 A,T2 B) : a(A),b(B)к{} |
|
|
|
|
||||
|
|
~cls(){} |
|
т |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
T1 sm1() |
|
|
// описание шаблона функции |
|
||||
|
|
|
о |
|
// суммирования компонент объекта obj_ |
|||||
|
|
{ return (T1)(a+b); |
|
|||||||
|
|
} |
|
|
|
|
|
|
|
|
|
|
T1 sm2(T1,T2); |
|
// объявление шаблона функции |
|
|||||
|
}; |
л |
|
|
|
|
|
|
|
|
|
б} |
|
|
|
|
|
|
|
|
|
|
templateи<class T1,class T2> |
|
|
|
|
|
||||
|
T1 cls<T1,T2>::sm2(T1 aa,T2 bb) |
// описание шаблона функции |
||||||||
и |
|
|
|
|
|
// суммирования внешних данных |
||||
Б |
{ return (T1)(aa+bb); |
|
|
|||||||
int main() |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
||
|
{ cls <int,int> obj1(3,4); |
|
|
|
|
|
|
|||
|
cls <double,double> obj2(.3,.4); |
|
|
|
|
|||||
|
cout<<"функция суммирования компонент объекта 1 |
|
= " |
|||||||
|
|
<<obj1.sm1()<<endl; |
|
|
|
|
|
|||
|
cout<<"функция суммирования внешних данных (int,int) |
= " |
||||||||
|
|
<<obj1.sm2(4,6)<<endl; |
|
|
|
|
|
|||
|
cout<<"вызов глобальной функции суммирования (int,int) |
= " |
||||||||
|
|
<<sm1(4,.6)<<endl; |
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
131 |
cout<<"функция суммирования компонент объекта 2 |
= " |
<<obj2.sm1()<<endl; |
|
cout<<"функция суммирования внешних данных (double,double)= " |
|
<<obj2.sm2(4.2,.1)<<endl; |
|
return 0; |
|
} |
|
6.2. Передача в шаблон класса дополнительных параметров
При создании экземпляра класса из шаблона в него могут быть переданы
не только типы, но и переменные и константные выражения: |
|
Р |
|||||||||
#include <iostream> |
|
|
|
|
|
|
|||||
using namespace std; |
|
|
|
|
|
|
|||||
template <class T1,int i=0,class T2> |
|
|
|
||||||||
|
|
УИ |
|||||||||
class cls |
|
|
|
|
|
|
|
|
|||
{ T1 a; |
|
|
|
|
|
|
Г |
|
|||
|
T2 b; |
|
|
|
|
|
|
|
|||
public: |
|
|
|
|
|
|
|
Б |
|
|
|
|
cls(T1 A,T2 B) : a(A),b(B){} |
|
|
|
|
||||||
|
~cls(){} |
|
|
|
|
|
|
|
|
||
|
T1 sm() |
|
|
|
|
|
|
|
|
||
|
//описание шаблона фун ции суммирования компонент |
||||||||||
|
{ // i+=3; |
// error member function 'int thiscall cls<int,2>::sm(void)' |
|||||||||
|
return (T1)(a+b+i); |
|
|
|
а |
|
|
||||
|
|
|
к |
|
|
|
|||||
|
} |
|
|
|
|
|
|
|
|
||
}; |
|
|
|
|
|
|
е |
|
|
|
|
int main() |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|||
{ cls <int,1,int> obj1(3,2); |
|
// |
в шаблоне const i инициализируется 1 |
||||||||
|
cls <int,0,int> obj2(3,2,1); |
т// error 'cls<int,0>::cls<int,0>':no overloaded |
|||||||||
|
|
|
|
о |
// function takes 3 parameter s |
|
|||||
|
cls <int,int,int> obj13(3,2,1); // |
error 'cls' : invalid template argument for 'i', |
|||||||||
|
|
|
|
и |
|
|
// constant expression expected |
|
|||
|
cls <int,int>лobj2(3,1); |
|
|
|
|||||||
|
|
// |
error (аналогично предыдущей) |
|
|||||||
|
cout<<obj1.sm()<<endl; |
|
|
|
|
|
|
|
|||
|
|
б |
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
} |
и |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
Результатом работы программы будет выведенное на экран число 6. |
|||||||||||
Б |
|
|
|
|
|
|
|
|
|
|
|
В этой программе инструкция template <class T1,int i=0,class T2> гово- |
рит о том, что шаблон класса cls имеет три параметра, два из которых − имена типов (Т1 и Т2), а третий (int i=0) − целочисленная константа. Значение кон- станты i может быть изменено при описании объекта cls <int,1,int> obj1(3,2). В этом случае инициализация константы i в инструкции template не требуется template <class T1,int i,class T2>.
132