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

Void myfunc(type1 X, type2 y)

{

cout<<"x = "<<x<<" y = "<<y<<"\n";

}

Void main()

{

myfunc(10,"Hello");

myfunc(5.15,13L);

}

Результат виконання програми наступний:

x = 10 y = Hello

x = 5.15 y = 13

У даному прикладі при генерації конкретних екземплярів функції myfunc(), типи даних type1 та type2 замінюються компілятором на типи даних int та char* або double та long відповідно.

8.6 Загальні відомості шаблонів класів

Шаблони класів надають можливість створювати класи, які параметризуються. Клас, який параметризується, створює сімейство споріднених класів, які можна застосовувати до будь-якого типу даних, передаваного як параметр. Найбільш широке застосування шаблони знаходять при створенні контейнерних класів. Контейнерним називається клас, який призначений для зберігання яким-небудь чином організованих даних і роботи з ними. Стандартна бібліотека C++ містить безліч контейнерних класів для організації структур даних різного вигляду (вони описані в розділі "Контейнерні класи").

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

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

Для засвоєння матеріалу доцільно розглянути версію класу, який не параметризується, "список".

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

class Node

{

public:

int d;

Node* next;

Node* prev;

Node (int dat = 0)

{

d = dat;

next = prev =0;

}

};

Оскільки цей клас буде описаний всередині класу, що представляє список, поля для простоти доступу із зовнішнього класу зроблені доступними (public). Це дозволяє обійтися без функцій доступу і зміни полів. Назвемо клас списку List:

class List

{

class Node

{

...

};

Node*pbeg,*pend;//Вказівки на початок та кінець списку

public:

List() {pbeg = 0;pend=0;} //Конструктор

~List(); // Деструктор

void add(int d); // Додавання вузла у кінець списку

Node * find(int i); // Пошук вузла по ключу

bool remove (int key); // Видалення вузла

// Вставка вузла d після вузла с ключем key

Node* insert(int key, int d);

void print();// Друк списку у прямому напрямі

void print_back();// Друк списку в оберненому напрямі

};

Розглянемо реалізацію методів класу. Метод add виділяє пам'ять під новий об'єкт типу Node і приєднує його до списку, оновлюючи вказівки на його початок та кінець:

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; // Оновлення вказівки на кінець списку

}

}

Метод find() виконує пошук вузла із заданим ключем і повертає вказівку на нього у разі успішного пошуку і 0 у разі відсутності такого вузла в списку:

Node* List::find(int d)

{

Node *pv = pbeg;

while(pv)

{

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

pv = pv->next;

}

return pv;

}

Метод insert() вставляє в список вузол після вузла з ключем key і повертає вказівку на вставлений вузол. Якщо такого вузла в списку немає, вставка не виконується і повертається значення 0:

Node * List::insert(int key, int d)

{

if(Node *pkey = find(key))

{ // Пошук вузла з ключем key

//Виділення пам’яті під новий вузол та його ініціалізація:

Node *pv = new Node(d);

// Встановлення зв’язку нового вузла з наступним:

pv->next = pkey->next;

// Встановлення зв’язку нового вузла з попереднім:

pv->prev = ркеу;

// Встановлення зв’язку попереднього вузла з новим:

pkey->next = pv;

// Встановлення зв’язку наступного вузла з новим:

if (ркеу != pend) (pv->next)->prev = pv;

// Оновлення вказівки на кінець списку,

// якщо вузол вставляється в кінець:

else pend = pv;

return pv;

}

return 0;

}

Метод remove видаляє вузол із заданим ключем із списку і повертає значення true у разі успішного видалення і false, якщо вузол з таким ключем в списку не знайдений:

bool List::remove(int key)

{

if(Node *pkey = find(key))

{

if (pkey == pbeg)

{ // Видалення з початку списку

pbeg = pbeg->next;

pbeg->prev = 0;

}

else if (pkey == pend)

{ // Видалення з кінця списку

pend = pend->prev;

pend->next = 0;

}

else

{ // Видалення з середини списку

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

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

}

delete pkey;

return true;

}

return false;

}

Методи друку списку в прямому і зворотному напрямі поелементно переглядають список, переходячи по відповідних посиланнях: