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

Void List ::print()

{

Node* pv = pbeg;

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

while(pv)

{

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

pv = pv->next;

}

cout << char(10);

}

Void List::print_back()

{

Node* pv = pend;

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

while(pv)

{

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

pv = pv->prev;

}

cout << char(10);

}

Деструктор списку звільняє пам'ять з-під всіх його елементів:

List::~List()

{

if(pbeg!=0)

{

Node* pv = pbeg;

while(pv)

{

pv = pv->next;

delete pbeg;

pbeg = pv;

}

}

}

Приклад програми, яка використовує клас List:

Void main()

{

List L;

L.add(5);

L.add(4);

L.insert(5,25);

L.insert(25,100);

L.print();

L.print_back();

L.remove(25);

L.print();

return;

}

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

list 5 25 100 4

list back 4 100 25 5

list 5 100 4

8.7 Створення шаблонів-класів

Клас List призначений для зберігання цілих чисел. Щоб зберігати в ньому дані будь-якого типу, потрібно описати цей клас як шаблон і передати тип в якості параметру.

Синтаксис опису шаблону:

template <опис_параметрів_шаблону> визначення_класу:

Параметри шаблону перераховуються через кому. В якості параметрів можуть використовуватися типи, шаблони і змінні.

Типи можуть бути як стандартними, так і визначеними користувачем. Для їх опису використовується ключове слово class. Усередині шаблону параметр типу може застосовуватися в будь-якому місці, де допустимо використовувати специфікацію типу, наприклад:

template <class Data> class List

{

class Node

{

public:

Data d;

Node* next;

Node* prev;

Node (Data dat = 0)

{

d = dat;

next = 0;

prev = 0;

}

};

Клас Data можна розглядати як формальний параметр, на місце якого при компіляції буде підставлений конкретний тип даних. Для будь-яких параметрів шаблону можуть бути задані значення за умовчанням, наприклад:

template<class Т> class myarray {/*..*/};

...

template<class K,class V,tempiate<class T>class С=myarray>

class Map

{

C<K> key;

C<V> value;

...

};

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

template<class Т, Т* p, class U = Т> class X{ /*...*/};

Методи шаблону класу автоматично стають шаблонами функцій. Якщо метод описується поза шаблоном, його заголовок повинен мати наступні елементи:

template <опис_параметрів_шаблону>

поверт_тип ім’я_класу <параметри_шаблону>::

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

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

template <class Data> void List<Data>::print()

{ / * тіло функції */ }

Тут <class Data> – опис параметра шаблону, void – тип значення, яке повертається функцією. List – ім'я класу, <Data> – параметр шаблону, print – ім'я функції без параметрів.

У разі декількох параметрів порядок їх проходження в описі параметрів і параметрах шаблону має бути один і той же, наприклад:

template<class T1, class T2> struct A

{

void f1 ();

};

template<class T2, class T1> void A<T2, T1 >::f1(){...}

Нижче перераховані правила опису шаблонів.

  1. Локальні класи не можуть містити шаблони як свої елементи.

  2. Шаблони методів не можуть бути віртуальними.

  3. Шаблони класів можуть містити статичні елементи, дружні функції і класи.

  4. Шаблони можуть бути похідними як від шаблонів, так і від звичайних класів, а також бути базовими і для шаблонів, і для звичайних класів.

  5. Усередині шаблону не можна визначати friend-шаблони.

Як приклад шаблону розглянемо повний опис класу двохзв'язного списку List з параметрами.

#include <iostream>

using namespace std;

template <class Data> class List

{

public:

class Node

{

public:

Data d;

Node* next;

Node* prev;

Node (Data dat = 0)

{

d = dat; next = 0; prev = 0;

}

};

Node* pbeg,*pend;

public:

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

~List();

void add(Data d);

Node* find(Data i);

bool remove (Data key);

Node* insert(Data key, Data d);

void print();

void print_back();

};

template <class Data>

List<Data>::~List()

{

if(pbeg!=0)

{

Node* pv = pbeg;

while(pv)

{

pv = pv->next;

delete pbeg;

pbeg = pv;

}

}

}

template <class Data>

void List<Data>::print()

{

Node* 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* 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* pv = new Node(d);

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

else

{

pv->prev = pend;

pend->next = pv;

pend = pv;

}

}

template <class Data>

typename List<Data>:: Node*

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

{

if(Node*pkey = find(key))

{

Node* pv = new Node(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>

typename List<Data>::Node*

List<Data>::find(Data d)

{

Node *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*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;

}