Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003), страница 8
Описание файла
DJVU-файл из архива "Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр DJVU-файла онлайн
Распознанный текст из DJVU-файла, 8 - страница
Шаблоны функций 42 у/ Максимальное из двух целочисленных значений хп1зпе ьпс сопнса гаах(зпс сопзга а, 1пс совести Ы ( кесикп а < Ь ? Ь : а; Более подробно этот вопрос будет рассмотрен в разделе 9.2, стр. 145, а пока в качестве правила примем следующее: объявления всех перегруженных версий функции следует помешать перед ее вызовом. 2.5.
Резюме ° Шаблоны функций определяют семейство функций для разных аргументов шаблона. ° При передаче аргументов шаблона происходит инстанцирование шаблонов функций для данных типов аргументов. ° Параметры шаблонов можно задавать явно. ° Шаблоны функций можно перегружать. ° При перегрузке шаблонов функций следует ограничивать вносимые изменения явным указанием параметров шаблона. ° Следует убедиться, что все перегруженные версии шаблонов функций размещены в программе до вызовов соответствующих функций. Глава 3 Шаблоны классов Подобно функциям, классы также могут быль параметризованы одним или несколькими типами. Типичным примером такой возможности могут служить классы контейнеров, которые применяются для работы с элементами определенного типа.
Такие классы контейнеров с неизвестными заранее типами элементов реализуются с помощью шаблонов классов. В этой главе в качестве примера шаблона класса рассматривается стек. 3.1. Реализация шаблона класса ЯасК Объявим и определим класс Ясас)с<> в заголовочном файле точно так же, как это делалось для'шаблонов функций (вопросы помещения объявлений и определений в отдельных файлах будут рассмотрены в разделе 7.3, стр. 113).
// Ьавйсв/всас)с1.Ьрр ()йпс1иде <чессог> ()1пс1ис(е <вМехсерг> // Элементы Ьоо1 енсу() сопит гесигп е1ешв.ешрсу()з Сетр1аге <Сурепаше Т> чо1д Ягас)с<Т>::ривЬ(Т сопвга е1еш) сешр1аге <Сурепаше Т> с1авв Ясас)с ( ргйчасе: вела::чессог<Т> е1ешв; роЬ11с: чойб ривЬ(Т сопвса); чоЫ рор(); Т Сор() сопит; // )(обавление элемента // Снятие элемента // Возврат элемента // с вершины стека // Возвращает Ггпе, // если стек пуст Глава 3. Шаблоны классов 44 е1еав.ривЬ ЬасК(е1ем)з // Добавление в стек // копии передаваемого // элемента семр1асе <сурепаме Т> чойс) ЯеасК<Т>::рор() ( Тй (е1евв.емрсу()) ( СЬгои вой::она ой канде("ЯеасК<>::рор():" емрсу всасК>); ) е1еав.рор ЬасК(]; // Удаление последнего элемента севр1асе <сурепаве Т> Т ЯсасК<Т»:ьор() сопвс 1х (е1емв.емрсу(]) ( сЬгои всд::оис об гапде(>ЯсасК<»:сор():" емрсу всасК")] ) гесигп е1еав.ЬасК()з // Возврат копии последнего элемента Как видите, для реализации шаблона класса используется шаблон класса чессог<> стандартной библиотеки С++.
Таким образом, отпадает необходимость заниматься реализацией управления памятью, конструктора копирования и оператора присвоения и можно сосредоточиться только на интерфейсе шаблона класса. 3.1.1. Объявление шаблонов классов Объявление шаблона класса выполняется аналогично объявлению шаблона функции: ему должна предшествовать инструкция, которая объявляет некоторый идентификатор в качестве параметра типа. Здесь также принято использовать в качестве идентификатора Т.
сеар1аае <Сурепаме Т> с1авв ЯеасК ( Как и для шаблонов функций, вместо ключевого слова сурепаае можно применять ключевое слово с1авв. сетр1асе <с1авв Т> с1авв ЯсасК ( З.1. реализация шаблона класса ягасК 45 Внутри шаблона класса идентификатор Т можно использовать в объявлениях членов и функций-членов так же, как и любой другой тип. В данном примере Т используется для объявления типа элементов как вектора значений с типом Т, для объявления ривЬ ( ] как функции- члена класса, которая получает в качестве аргумента константную ссылку на обьект типа т, и для обьявления функции Сор ( ), которая возвращает элемент типа Т. сешр1асе <сурепаше т> с1авв ЯеасК ( рттчасе: вес]::чессот<т> е1ешв; // элементы Класс имеет тип ЯеасК<т>, где Т является параметром шаблона. Таким образом, каждый раз, когда требуется использовать тип этого класса в объявлении, следует указывать ЯгасК<т>.
Если, например, необходимо объявить собственные конструктор копирования и оператор присвоения, это должно выглядеть так: 1, Сешр1аге <Сурецаше Т> с1авв ЯсасК ( ЯсасК (ЯгасК<т> сопвсй]; // Конструктор копирования ЯеасК<т>й оретапог = (ягасК<т> сопвкй); // Оператор присвоения ) Однако если требуется указать имя, а не тип класса, следует использовать только Я сасК. Это делается при указании имени класса, его конструктора н деструктора. 3.1.2.
Реализация функций-членов Для того чтобы опредшппь функцию-член шаблона класса, нужно указать, что это шаблон функции; при этом необходимо использовать полное имя типа шаблона класса. Таким образом, реализация функции-члена рань ( ) типа ясаск<т> имеет следующий вид: Сешр1аге <сурепке Т> чоЫ ясасК<т>::ривЬ(т сопвсй е1еш) е1ешв.рпвЬ ЬасК(е1еш); // Добавление копии // элемента в стек ) ! В соответствии со стандартом, нз этого правила имеются некоторые исключения (см. раздел 9.2Э, сгр. 150).
Однако ддк гарантии корректности лучше использовать полный тип. рпЬ11с: Ясас1с(): чотс] рпвЬ(Т сепией)г чей рор(]; Т Сор() сопит; // Конструктор // Добавление элемента // Снятие элемента со стека // Возврат элемента // с вершины стека Глава 3. Шаблоны классов 46 Здесь для элемента вектора вызывается функция ривЬ Ьас)с(), которая и добавляет его в конец вектора. Заметим, что функция рор ЬасК ( ) вектора удаляет последний элемент, но не возвращает его, что связано с вопросами безопасности исключений. Реализовать полностью безопасную в плане исключений функцию рор ( ), возвращающую удаленный элемент, невозможно (этот вопрос впервые был рассмотрен Томом Каргиллом (Тощ СагрН) в (9); кроме того, этот вопрос детально рассматривается в (36)).
Однако если игнорировать не- безопасность данной функции в плане исключений, то можно написать функцию рор ( ), возвращающую только что удаленный элемент. Здесь Т используется просто для объявления локаяьной переменной соответствующего типа. севр1асе <сурепаве т> чоЫ ЯпасК<Т>::рор() ( 16 (е1евв.европу()) ( сЬхом всс)::опп От галде("Ятаск<>::рор():" еврсу асасК"); Т е1ев = е1евв.ЬасК(); // Сохранение копии // последнего элемента // Его удаление // Возврат сохраненной // копии элемента Поскольку поведение функций вектора ЬасК() (возврацающей последний элемент) и рор Ьас)с() (удаляющей последний элемент) не определено для случая, когда вектор не содержит ни одного элемента, требуется проверка, не является ли стек пустым. Если он пуст, генерируется исключение типа зМ::оис об галде.
Такое же исключение генерируется и в функции Сор ( ), которая возвращает (но не удаляет) элемент, находящийся на вершине стека. Севр1ате <Сурепаве Т> Т ЯпасК<Т>:гбор() сонат ( 16 (е1евз.еврсу()) ( СЬГОМ Впд::ОПС Ой ГаПдЕ("ЯпаСК<>:гбср():" еврсу зсасК"); ) гекнкп е1ева.ЬасК(); // Возврат копии // последнего элемента ) Разумеется, точно так же, как и в случае любых других функций-членов, функции- члены шаблонов классов можно реализовать как встраиваемые функции, располагающиеся внутри объявления класса, например: З.2. Использование шаблона класса Б(асК сешр1апе <аурелио Т> с1авв ЯсасК( чоХЙ рцвЬ (Т сопвай е1еш) ( е1ешв.рцвЬ ЬасК(е1еш); // Добавление копии // элемента в стек 3.2. Использование шаблона класса ЯасЕ Для того чтобы использовать объект шаблона класса, необходимо явно указать аргументы шаблона.
В приведенном ниже примере проиллюстрировано применение шаблона класса ЯсасК<>. // Ьав1св/всасК1севс.срр 41пс1цйе <Ховсгеаза> МХпс1ийе <всг1пд> ()Хпс1цйе <свсй11Ь> $1пс1ийе "всасК1.Ьрр" Хпс назп; агу ( ЯпасК<1пп> ХпСЯСасК/ // Стек элементов типа Хпп ЯсасК<всй::всг1пд> всг1пдЯсасК; // Стек элементов типа всг1пд // Работа со стеком целых чисел ХпсЯсасК.рцвЬ(7); вСЙ::соцп « ХппяпасК.Сор() « вСЙ::епй1; // Работа со стеком строк ваг1пдЯСасК.рцвЬ("Ье11о"); всй::соис « всг1пдЯсасК.сор() « всй::епй1; всгзпдЯсасК.рор(); впг1пдЯСасК.рор(); ) сассЬ (вСЙ::ехсерСХоп сопела ех) ( вСЙ::сегг « "Ехсерп1оп: « ех.ыпас() « всй::епй1; гепцгп ЕХХТ РАХОВЕ; // Выход из программы // с указанием ошибки Глава 3.
Шаблоны классов чоЫ боо(ЯсасК<1пс> сопвса в) // Параметр в является стеком целых чисел ( ЯсасК<1пс> 1всасК[10]; // 1всасК представляет собой // массив ив 10 стеков целых чисел применение шаблонов классов более Используя определение типов, можно сделать удобным. Сурес)ей ЯгасК<1пг> 1псЯСасК; чей 1оо(1псясасК сопвса в) // Параметр в является стеком целых ( 1псЯСасК ТвпасК[10]; // 1вгасК // массив чисел представляет собой ив 10 стеков целых чисел Заметим, что в С++ при определении с помощью суре<)еб задается псевдоним типа, а не новый тип. Таким образом, после определения типа суре<)ег ЯкасК<йпс> 1пСЯСасК; Обьявление ЯсасК<1пс> указывает, что внутри шаблона класса в качестве типа 1 будет использоваться 1пш Таким образом, 1псЯСас)с создается как обьект на базе вектора с элементами типа 1пк, и для всех вызываемых функций-членов инстанцнруется код для этого типа.