Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.doc
Скачиваний:
77
Добавлен:
07.03.2016
Размер:
1.78 Mб
Скачать

Void main()

{

List<int> List_int;

List_int.add(5);

List_int.add(4);

List_int.insert(5,25);

List_int.insert(25,100);

List_int.print();

List_int.print_back();

List_int.remove(25);

List_int.print();

}

Результат роботи програми:

list 5 25 100 4

list back 4 100 25 5

list 5 100 4

У функції main() створюється за допомогою шаблону об'єкт List_int (цей процес називається інстанціюванням). У загальному вигляді при описі об'єкту після імені шаблону в кутових дужках перераховуються його аргументи:

ім’я_шаблону <аргументи>

ім’я_об’єкта [(параметри_конструктору)];

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

tempiate<class Т = char> class String;

String <>* p;

Для спрощення використання шаблонів класів можна застосувати перейменування типів за допомогою typedef:

typedef List <double> Ldb1;

Ldb1 List_double;

Ми розглянули приклад коли клас Node знаходиться усередині класу List. Якщо ці класи представлені роздільно, тоді опис класу двохзв’язного списку матиме наступний вигляд:

#include <iostream>

using namespace std;

template <class Data> class Node

{

public:

Data d;

Node* next;

Node* prev;

Node (Data dat = 0)

{

d = dat;

next = 0;

prev = 0;

}

};

template <class Data> class List

{

Node<Data>* pbeg,*pend;

public:

List(){pbeg = 0;pend=0;}

~List();

void add(Data d);

Node<Data>* find(Data i);

bool remove (Data key);

Node<Data>* insert(Data key, Data d);

void print();

void print_back();

};

template <class Data>

List<Data>::~List()

{

if(pbeg!=0)

{

Node<Data>* pv = pbeg;

while(pv)

{

pv = pv->next;

delete pbeg;

pbeg = pv;

}

}

}

template <class Data>

void List<Data>::print()

{

Node<Data>* pv = pbeg;

cout << char(10) << " list ";

while(pv)

{

cout << pv->d << " ";

pv = pv->next;

}

cout << char(10);

}

template <class Data>

void List<Data>::print_back()

{

Node<Data>* pv = pend;

cout << char(10) << " list back ";

while(pv)

{

cout << pv->d << " ";

pv = pv->prev;

}

cout << char(10);

}

template <class Data>

void List<Data>::add(Data d)

{

Node<Data>* pv = new Node<Data>(d);

if(pbeg == 0)pbeg = pend = pv;

else

{

pv->prev = pend;

pend->next = pv;

pend = pv;

}

}

template <class Data>

Node<Data>* List<Data>::insert(Data key,Data d)

{

if(Node<Data>*pkey = find(key))

{

Node<Data>* pv = new Node<Data>(d);

pv->next = pkey->next;

pv->prev = pkey;

pkey->next = pv;

if(pkey!=pend)(pv->next)->prev = pv;

else pend = pv;

return pv;

}

return 0;

}

template <class Data>

Node<Data>* List<Data>::find(Data d)

{

Node<Data> *pv = pbeg;

while(pv)

{

if(pv->d == d)break;

pv = pv->next;

}

return pv;

}

template <class Data>

bool List<Data>::remove(Data key)

{

if(Node<Data>*pkey = find(key))

{

if (pkey == pbeg)

{

pbeg = pbeg->next;

pbeg->prev = 0;

}

else if (pkey == pend)

{

pend = pend->prev;

pbeg->next = 0;

}

else

{

(pkey->prev)->next = pkey->next;

(pkey->next)->prev = pkey->prev;

}

delete pkey;

return true;

}

return false;

}

При визначенні синтаксису шаблону було сказано, що в нього, окрім типів і шаблонів, можуть передаватися змінні. Вони можуть бути цілого або перерахованого типу, а також вказівками або посиланнями на об'єкт або функцію. У тілі шаблону вони можуть застосовуватися в будь-якому місці, де допустимо використовувати константний вираз. Як приклад створимо шаблон класу, що містить блок пам'яті певної довжини і типу:

template <class Type, int kol>

class Block

{

public:

Block(){p = new Type [kol];}

~Block(){delete [] p;}

operator Type * ();

protected:

Type * p;

};

template <class Type, int kol>

Block <Type, kol>:: operator Type *()

{

return p;

}

В даному випадку опис об'єкту має вигляд:

Block <char, 128> buf;

Block <monstr, 100> stado;

Після створення та відлагодження шаблони класів зручно поміщати в заголовні файли.