Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Лафоре Р. -> "Объектно-ориентированное программирование в С++" -> 246

Объектно-ориентированное программирование в С++ - Лафоре Р.

Лафоре Р. Объектно-ориентированное программирование в С++ — М.: Питер, 2004. — 992 c.
Скачать (прямая ссылка): obektnoorentprogramm2004.djvu
Предыдущая << 1 .. 240 241 242 243 244 245 < 246 > 247 248 249 250 251 252 .. 341 >> Следующая


st[++top] - var; }

Имя Stack<Type> используется для того, чтобы идентифицировать класс, чьим методом является push().

Для обычного, нешаблонного метода одного имени Stack было бы достаточно:

void Stack: :push(int var) //StackO как нешаблонная функция {

st[++top] = var; }

но для шаблона функции приходится использовать еще и шаблонный аргумент: Stack<Type>.

Итак, имя шаблонного класса выглядит по-разному в зависимости от контекста. Внутри спецификации класса это просто само имя: Stack. Для методов, определенных вне классов, это имя класса и имя шаблонного аргумента: Stack<Type>. Когда вы определяете реальные объекты для хранения конкретного типа данных, именем шаблонного класса будет являться имя класса и имя типа: Stack<float>. Например:

class Stack //Описатель класса Stack

{ }:

void Stack<Type>:: push (Type var) //определение pushO { }

Stack<float> si: //обьект типа Stack<float>

Нужно быть внимательным, чтобы корректно писать имена, соответствующие контексту. Очень просто можно забыть про <Туре> или <float>, которые нужно добавлять к Stack. Компилятор не переносит таких ошибок. Шаблоны классов 653

Хотя это и не акцентировалось в предыдущем примере, но нужно всегда крайне аккуратно отслеживать правильность синтаксиса, когда метод возвращает значение своего собственного класса. Предположим, мы определили класс Int, который защищает законные права класса целых чисел (это обсуждалось в упражнении А главы 8 «Перегрузка операций»). Если бы вы использовали внешнее определение метода xfuncQ данного класса, который возвращает значения типа Int, тогда пришлось бы писать Int<Type> и в качестве типа функции, и в качестве левой части оператора явного задания функции:

Int<Type> Int<Type>::xfunc(іnt arg) { }

Имя класса, являющееся типом аргумента функции, с другой стороны, вовсе не обязано включать в себя обозначение <Туре>.

Создание класса связных списков с помощью шаблонов

Рассмотрим еще один пример, в котором шаблоны помогают в создании классов-хранилищ данных. Для этого мы модифицируем программу LINKLIST из главы 10 «Указатели», которую советуем посмотреть сейчас еще разок. Требуется, чтобы не только класс IinkList был переделан в шаблон, но и чтобы структура Link, которая реально хранит каждый элемент данных, тоже стала шаблоном.

Листинг 14.5. Программа TEMPLIST

// tempi і st.срр

// Шаблон связных списков

finclude <iostream>

using namespace std:

///////////////////////////////////////////////////////////

tempiate<class TYPE> //структура link<TYPE>

struct link //элемент списка

//( внутри этой структуры определение link означает

// І іnk<TYPE> ) {

TYPE data: //элемент данных

link* next: //указатель на следующий элемент

}•'

/////////////////////////////////////////////////////////// tempiate<class TYPE> //класс linklist<TVPE> class linklist //список ссылок

//(внутри этого класса linklist означает linklist<TYPE>) {

private:

link<TYPE>* first: //указатель на первую ссылку public:

IinklistO //конструктор без аргументов

{ first = NULL: } //первой ссылки нет //примечание: можно вписать еще деструктор: для упрощения //листинга, не приводим его здесь.

void additenKTYPE d): //добавить данные (одна ссылка) void displayO: //вывести все ссылки

}:

продолжение ?> 654

Глава 14. Шаблоны и исключения

Листинг 14.5 (продолжение)

/////////////////////////////////////////////////////////// tempiate<class TYPE>

void linklist<TYPE>::additem(TYPE d) //добавление данных {

link<TYPE>* newlink = new link<TYPE>: //создать новую

// ссылку

newlink->data = d: //занести туда данньїе newlink->next = first; //то есть ссылку на следующий элемент first = newlink: //теперь первая ссылка указывает на

//данную ссылку

}

// ........................................

tempiate<class TYPE>

void linklist<TYPE>::display() //вывод всех ссылок {

link<TYPE>* current = first: //указатель - на первую ссылку

while( current != NULL ) //выйти после последней ссылки {

cout « endl « current->data: //вывести на экран

current = current->next: //сдвинуться на следующую ссылку

}

}

//....................

int mainO {

linklist<double> Id:

ld.additem(151.5): ld.additem(262.6); ld.additem(373.7); ld.displayO:

linklist<char> Ich:

1ch.addi tem('a'): 1ch.addi tem('b'): lch.additemt'с'): Ich.displayO; cout « endl:

return 0:

} " " :

B main() мы определяем два связных списка: один — для хранения чисел типа double, другой — для хранения символов (типа char). В каждый из них заносим по три значения с помощью метода additem() и выводим все значения на экран с помощью display(). Результаты работы программы:

373.7

262.6

151.5

с

b

а

И класс Linklist, и структура link пользуются шаблонным аргументом TYPE для . подстановки любого типа данных (ну, конечно, не совсем любого: мы позднее

//Id - обьект linklist<double> //добавить три числа double в список Id

//вывести весь список Id //Ich - обьект I1nklist<char> //три символа (char) - в список Ich
Предыдущая << 1 .. 240 241 242 243 244 245 < 246 > 247 248 249 250 251 252 .. 341 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100