Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lekc8.doc
Скачиваний:
5
Добавлен:
18.11.2019
Размер:
72.19 Кб
Скачать

2 Визначення функцій-членів шаблона класу

Функції-члени шаблона класу можуть визначатися в тілі класу (тобто як вбудовані) або зовні тіла класу. В останньому випадку її визначення має вигляд:

template <class T1 ідентифікатор1,

T2 ідентифікатор2,...,

TN ідентифікаторN>

тип ім’я класу

template <class T1 ідентифікатор1,

T2 ідентифікатор2,...,

TN ідентифікаторN>

:: ім’я функції (список параметрів)

{

//Тіло функції

}

3 Використання шаблонів

Дуже часто шаблони використовуються для створення колекцій, тобто класів, що представляють з себе набір об'єктів одного і того ж типу. Найпростішим прикладів колекції буде масив. Назвемо нову структуру даних вектор vector.

template <class T>

class vector

{

public:

vector():nitem(0),items(0){};

~vector () {delete items;};

void insert (const T& t)

{ T* tmp = items;

items = new T[nitem + 1];

memcpy (items, tmp, sizeof(T) *nitem);

item[++nitem] = t;

delete tmp; }

void remove (void)

{ T * tmp = items;

items = new T [ --nitem];

memcpy (items, tmp, sizeof (T) *nitem);

delete tmp;

}

const T& operator [] (int index) const

{

if ((index < 0) || (index >= nitem))

throw IndexOutOfRange;

return items[index];

}

T& operator[](int index)

{

if ((index < 0) || (index >= nitem))

throw IndexOutOfRange;

return items[index];

}

private:

Т* items;

int nitem;

};

Окрім конструктора і деструктора у нашого вектора є тільки три методи: метод insert додає в кінець вектора новий елемент, збільшуючи довжину вектора на одиницю, метод remove видаляє останній елемент вектора, зменшуючи його довжину на одиницю, і операція [.] звертається до n-ому елемента вектора.

Параметр шаблона vector - будь-який тип, у якого визначені операція привласнення і стандартний конструктор. Згенерувати конкретний клас з шаблона можна явно, записавши:

template vector<int>;

Цей оператор не створить ніяких об'єктів типу vector<int> але проте викличе генерацію класу зі всіма його методами.

Одним з цікавих методів використовування шаблонів є уточнення поведінки за допомогою додаткових параметрів шаблона. Припустимо, ми пишемо функцію сортування вектора:

template <class T>

void sort_vector(vector<T>& vec)

{

for (int i = 0; i < vec.size() -1; i++)

for (int j = i; j < vec.size(); j++) {

if (vec[i] < vec[j]) {

Т tmp = vec[i];

vec[i]= vec[j];

vec[j]= tmp;

}

}

}

Ця функція працюватиме добре з числами, але якщо ми схочемо її використовувати для масиву вказівників на рядки (char*), то результат буде не зовсім очікуваний. Сортування відбудеться не по значенню рядків, а за їх адресами (операція менше для двох вказівників -це порівняння значень цих вказівників, тобто адрес величин, на які вони вказують, а не самих величин). Щоб виправити недолік, додамо другий параметр до шаблону:

template <class Т, class Compare>

void sort__vector (vector<T>& vec)

{

for (int i = 0; i < vec.size() - 1; i++)

for (int j = i; j < vec.size(); j++) {

if (Compare:: less (vec [i], vec[j])){

Т tmp = vec [i];

vec [i] = vec[ j ];

vec[j]= tmp;

}

}

}

Клас Compare повинен реалізовувати статичну функцію less, що порівнює два значення типу T. Для цілих чисел цей клас може виглядати таким чином:

class Comparelnt

static bool less(int а, int b) { return а < b; };

і сортування вектора буде мати вигляд

vector<int> vec;

sort<int, Compareint>(vec);

Для вказівників на байт (рядків) можна створити клас class CompareCharStr

static bool less(char* а, char* b)

{ return strcmp(а,b) >= 0); };

і, відповідно, сортувати за допомогою виклику

vector<char*> svec;

sort<char*, CompareCharStr>(svec);

Як легко помітити, для всіх типів, для яких операція менше має потрібний нам сенс, можна написати шаблон класу порівняння:

template<class T> Compare

static bool less (Т а, T b) { return а < b; };

і використовувати його в сортуванні (зверніть увагу на пропуск між кутовими дужками, що закриваються, в параметрах шаблона; якщо його не поставити, компілятор спутає дві дужки з операцією зсуву):

vector<double> dvec;

sort<double, Compare<double> >(dvec);

Щоб не захаращувати запис, скористаємося можливістю задання значення параметра за замовчуванням. Так само, як і для аргументів функцій і методів, для параметрів шаблона можна визначити значення за замовчуванням. Остаточний вид функції сортування буде наступний:

template <class Т, class C = Compare<T> >

void sort_vector(vector<T>& vec)

{

for (int i = 0; i < vec.size() - 1; i++)

for (int j = i; j < vec.size (); j++) {

if (C::less(vec[i], vec[j])) {

Т tmp = vec[i];

vec[i]= vec[j];

vec [ j] = tmp;

}

}

}

Другий параметр шаблона іноді називають параметром-штрих, оскільки він лише модифікує поведінку класу, який маніпулює з типом, який визначений першим параметром.

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