Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lutsik_Yu_A_Obektno_orientir_programmir_na_yaz.pdf
Скачиваний:
72
Добавлен:
11.05.2015
Размер:
4 Мб
Скачать
☆
}
void decrem(void)
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; // удаление временного массива

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]