
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Шаблоны Параметризированные классы
Параметризированный класс – некоторый шаблон, на основе которого можно строить другие классы. Этот класс можно рассматривать как некоторое описание множества классов, отличающихся только типами их данных. В С++ используется ключевое слово template для обеспечения параметрического полиморфизма. Параметрический полиморфизм позволяет использовать один и тот же код относительно различных типов (параметров тела кода). Это наиболее полезно при определении контейнерных классов. Шаблоны определения класса и шаблоны определения функции позволяют многократно использовать код, корректно по отношению к различным типам, позволяя компилятору автоматизировать процесс реализации типа.
Шаблон класса определяет правила построения каждого отдельного класса из некоторого множества разрешенных классов.
Спецификация шаблона класса имеет вид:
template <список параметров>
class объявление класса
Список параметров класса-шаблона представляет собой идентификатор типа, подставляемого в объявление данного класса при его генерации. Идентификатору типа предшествует ключевое слово class или typename. Рассмотрим пример шаблона класса работы с динамическим массивом и выполнением контроля за значениями индекса при обращении к его элементам.
#include "iostream.h"
#include "string.h"
template <class T> // или иначе template <typename T>
class vector
{ T *ms;
int size;
public:
vector() : size(0),ms(NULL) {}
~vector(){delete [] ms;}
void inkrem(const T &t) // увеличение размера массива на 1 элемент
{ T *tmp = ms;
ms=new T[size+1]; // ms - указатель на новый массив
if(tmp) memcpy(ms,tmp,sizeof(T)*size); // перезапись tmp -> ms
ms[size++]=t; // добавление нового элемента
if(tmp) delete [] tmp; // удаление временного массива
}
void decrem(void) // уменьшение размера массива на 1 элемент
{ T *tmp = ms;
if(size>1) ms=new T[--size];
if(tmp)
{ memcpy(ms,tmp,sizeof(T)*size); // перезапись без посл.элемента
delete [] tmp; // удаление временного массива
}
}
T &operator[](int ind) // определение обычного метода
{ // if(ind<0 || (ind>=size)) throw IndexOutOfRange; // возбуждение
// исключительной ситуации IndexOutOfRange
return ms[ind];
}
};
void 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;
}
Класс vector наряду с конструктором и деструктором имеет 2 функции: increm – добавление в конец вектора нового элемента, dekrem – уменьшение числа элементов на единицу и операция [] обращения к i-му элементу вектора.
Параметр шаблона vector – любой тип, у которого определены операция присваивания и операция new. Например, при задании объекта типа vector <int> происходит генерация конкретного класса из шаблона и конструирование соответствующего объекта VectInt, при этом тип Т получает значение типа int. Генерация конкретного класса означает, что генерируются все его компоненты-функции, что может привести к существенному увеличению кода программы.
Выполнение функций
VectInt.increm(3);
VectInt.increm(26);
VectInt.increm(12);
приведет к созданию вектора (массива) из трех атрибутов (3, 26 и 12 ).
Сгенерировать конкретный класс из шаблона можно, явно записав:
template vector<int>;
При этом не будет создано никаких объектов типа vector<int>, но будет сгенерирован класс со всеми его компонентами.
В некоторых случаях желательно описания некоторых компонент-функций шаблона класса выполнить вне тела шаблона, например:
#include "iostream.h"
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() // описание шаблона функции
{ return (T1)(a+b); // суммирования компонент объекта obj_
}
T1 sm2(T1,T2); // объявление шаблона функции
};
template <class T1,class T2>
T1 cls<T1,T2>::sm2(T1 aa,T2 bb) // описание шаблона функции
{ return (T1)(aa+bb); // суммирования внешних данных
}
void 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;
cout<<"функция суммирования компонент объекта 2 = "
<<obj2.sm1()<<endl;
cout<<"функция суммирования внешних данных (double,double)= "
<<obj2.sm2(4.2,.1)<<endl;
}