
- •1.Объявление и определение класса.
- •3. Дружественные функции.
- •4. Пеpегpузка опеpаций ( синтаксис operator)
- •5. Статические компоненты класса.
- •7. Иерархия классов ( последовательность работы конструкторов и деструкторов )
- •8. Доступ к наследуемым компонентам
- •9. Виртуальные функции (когда применяются, форма вызова)
- •10 . Шаблоны ( пример template)
- •15 Преобразование типов данных.
- •17 Ввод-вывод в файл. Сохранение объектов в файле.
- •18 Обработка исключений (блоки try, throw, catch)
- •Примеры обработки исключительных ситуаций
- •20. Паттерны и их классификация. Принцип классификации паттернов проектирования
- •Паттерны проектирования классов/обьектов
- •21. Абстрактная фабрика.
- •22. Классификация типов данных. Система типов
- •Oбщий взгляд
- •Класс String
- •Объявление строк. Конструкторы класса string
- •Операции над строками
- •Цикл foreach
- •Наследование
- •Добавление полей потомком
- •Конструкторы родителей и потомков
- •Интерфейсы
- •Две стратегии реализации интерфейса
- •Преобразование к классу интерфейса
10 . Шаблоны ( пример template)
Параметризированный класс представляет собой некоторый шаблон (template), определяющий правила построения отдельного класса из множества разрешенных. Рассмотрим пример шаблона для построения стека (Stack) элементов типа Type:
template <class Type> class Stack{ Type *top, *sp; // указатели на начало и текущее состояние стека int size; // размер стека public: Stack(int n) {top=sp=new Type[size=n]; } ~Stack() {delete[] top; } // Операция += перегружается как операция “заталкивания” в стек; // cerr - стандартный поток для вывода сообщений об ошибках на дисплей void operator+=(Type v) { if (size>sp-top) *sp++=v; else cerr<<“Error\n”; } // Операция --перегружается как операция извлечения из стека Type operator--() { if (sp==top){ cerr<<“Error:\t”; return *sp; } return *--sp; } };
Имея шаблон, можно объявить стек с любым типом элементов:
void main () { Stack <int>si(2); // Объявление стека целых размером 2 si+=100; // Целое заталкивается в стек si +=234; si+=567; // Ошибка-результат Error cout<<--si<<endl; // Извлекается 234 cout<<--si<<endl; // Извлекается 100 cout<<--si<<endl; // Ошибка - результат Error:100 }
Здесь методами класса являются встроенные функции. Если бы их определяли вне класса, то следовало бы их записать как параметризированные функции:
template <class Type> Type Stack<Type>:: operator--() { if (sp==top){ cerr<<“Error:\t”; return *sp; } return *--sp; } template <class Type> void Stack<Type>:: operator+=(Type v) { if (size>sp-top) *sp++=v; else cerr<<“Error\n”; } )
Параметром шаблона, который передается в конструируемый класс, является Type. Его значением может быть не только встроенный, но и введенный пользователем тип. Для того, чтобы построить, например, стек комплексных чисел, надо описать в программе соответствующий класс, а затем объявить Stack<Complex>ss(3);
К параметризированным классам примыкают контейнеры классов. Контейнер – множество классов, которые отличаются только типами используемых в них данных; контейнеры содержат типовые структуры и типовые операции над данными, входящими в эти структуры. В библиотеке системы Borland C++ содержатся контейнеры, которые включают бинарные деревья, кэш-таблицы, списки, векторы, массивы, очереди, словари, множества и стеки.
Из этих структур можно конструировать классы с различными типами данных. Ниже приведена программа построения массива объектов типа double c использованием класса TSArrayAsVector, для которого задан шаблон в библиотеке системы.
#include <iostream.h>
#include <classlib\arrays.h>
void main(void){
TSArrayAsVector<double>a(10); // a - контейнер объектов типа double, //10 - число объектов в контейнере;объекты в контейнере отсортированы
double j;
for(int i=0; i<10; i++){
cin>>j;
a.Add(j); } // добавление объектов в контейнер
for (i=0; i<10; i++)
cout<<a[i]<<'\t';
}
В общем случае конструктор TSArrayAsVector имеет следующий вид:
TSArrayAsVector(int upper, int lower=0,int delta=0),
где upper – верхняя граница индекса, lower - нижняя его граница , delta – приращение числа объектов. Если в предыдущем примере записать ненулевое приращение, например, объявить a(10,0,10), то после введения 10-го объекта в массив автоматически добавится еще 10 полей для новых объектов. Это позволяет решать проблему расширения массивов и не требует оценки размера массива на этапе проектирования программы.