Г. Шилдт - Полный справочник по C++ (1109478), страница 73
Текст из файла (страница 73)
*/ год( ; веаге<соцпез веаге++) 1еетв[веаге] = (х) 0[ ) фпе зьафп() зпс зшпю[7] = (О, 1, 2, 3, 4, 5, 8)з с)заг ест[ 18) = "Обобщенные функцим"з з.пс з.; соос « "Неуплотненная часть целочисленного массива: Гог(з=оз 1<7( 1++) соцс «пцыв [з.] « соне « епц1[ соос « "Неуплотненная часть строки: еог(1=0; 1<18[ ь++) соне « вег[з] « соце « епц1[ соязрас[:(позлв, 7, 2, 4); соырасе[вег, 18, б, 10); соцс « "Уплотненный целочисленный массив: дог[1=0з 1<7; 1<+) соие « пцщв[з) « соне «еж$1[ соцс « "Уплотненная целочисленная строка: Часть 11, Язык С++ е е е Гок О =се 1<18; 1+<) соме « яек 111 « со е « епб1е 6 сегцкл 0 $) Эта программа уплотняет массивы двух типов: целочисленный и строку, Олнако функция еоараее() может работать с массивом любого типа. Результаты работы программы показаны ниже.
е Неуллоткеяяыи целочисленный массиве 0 1 2 3 4 5 6 Неуплотненные целочислемееый массиве 0 б о б ж е и н а я Е у н к ц и я Уплотиеиныи целочисленный массиве О 1 5 б 0 0 0 Уплотненная строка: 0 б о б ы е и я а я и и я Как видим, во мцогих случаях шаблоны являются вполеее естественными. Если логика Функции ис зависит от типа данных, ес можно преобразовать в шаблонную. ~ Обобщенные классы Кроме обобшеииых функции можно определить обобшсипые классы. При этом создастся класс, в котором определены все алгоритмы, однако фактический тип данпых задается в качестве параметра при создании объекта. Обобшеипыс классы оказываются полезными, если логика класса це зависит от типа данных.
Например, к очередям, состояшим из целых чисел или символов, можно применять один и тот же алгоритм. а для поддержки связигиых списков адресов рассылки и мест для парковки автомобилей использовать адин и тот жс механизм. Объявление обобшеииого класса имеет следуюший вид. еекер1асе <с1авв Ттия> с1ава мия класси Здесь параметр Ттеел задает тип данных, который уточняется при создании экземпляра класса. При необходимости можно опрсдслизь несколько обобшснных типов, используя список имен, раздслсниьех запятой.
Конкрстцый экземпляр обобшснцого класса создастся с помошью следуюшсй синтаксической конструкции. й ммя клиссп <еятс шт ибьекеееас Здесь параметр тил задает тип данных„которыми оперирует класс. Функции — члены сбобшециого класса автоматически становится обобщенными. Для их объявления ие обязательно использовать ключевос слово ееяер1аее.
Следуюшая программа использует обобшспцый класс аеае1с (оке. главу 11). Теперь его можно примсцять для храцсция объектов любого типа. В даешом примере создаются стеки символов и действительных чисел. ГУ Демонстрация обобжекмого стека. №гпс1цбе '<№овекеаел> ця1ееа палееерасе вассе сопев 1ПЕ 5125 = 10; Глава 18. Шаблоны //' Создаем обобыенный класс всасК.
Сетр1аее <с1авв БеасКТуре> с1авв виасК ( БиасКТуре весК(БХЕЕ]; // Содержит злементы стека. 1пс сов; // индекс верзилы сбавка. риЬ11с: всасК() ( сов = О; ) // иниииализируе стек. чо1с) ривЬ(БСасКТуре оЫ; // Заталкивает обьект в стек. БиасКТуре рор(); // Выталкивает объект из стека. // Заталкиваем объект в стек. Сеир1аее <с1авв БсасКТуре> чо10 веасК<БСасКТуре>::ривЬ(БСасКТуре оЫ ( 11(еов==Б12Е) ( сопи « "Стек полон.1п"; теситп; ) вдсК(Сов] = оЬ; сов++) ) // Выталкиваем объект из стека. Сетр1аее <с1авв БкасКТуре> БиасКТуре вдасК<БСасКТуре>::рор() ( 11(сов==-0) соие « "Стек пуст..М"; тесихп 0; // Если стек пуст.
возврашается константа пи11. ) сов--; хеситп вссК(сов]) тпс шаып() ( // Лемонстраиия стека символов. всасК<сЬах> в1, в2; // Создаем два стека символов. 1пс 1; в1. ривЬ ( ' а ' ); в2.ривЬ('х')) в1.ривЬ('Ь'); в2.ризи('у'); в1.ривЬ ( ' с' ); в2.ривп('з')) сот(1=0; 1<3; 1++) соил « "Выталкиваем в1: " « в1.рор() « "(п"; сот(1†" 0; 1<3; 1++) соис « "Выталкиваем в2: " « в2.рор() « '1п"; // Демонстраиия стека действительных чисел всасК«)оиЬ1е> бв1, бв2; // Создаем два стека // действительных чисел.
бв1.ривЬ(1.1); бв2.ривЬ(2.2); <(в1.ривЬ(3.3); <(в2.ривЬ(4.4); бв1.ривЬ(5.5); Часть 11. Язык Стт сЪз2.ризЬ(б.б); хох(1=0; 1<3; 1++) соса « "Выталкиваем с)з1: " « е)з1.рор() « бтп'; Гох(1=.0; 1<3; х++) соис « "Выталкиваем с)з2: " « дз2.рор О « "(и"; хесцхп 0; ) Как видим, объявление обобщенного класса мало отличается от объявления обобщенной функции. Фактический тип данных, размещаемый в стеке, в объявлении класса заменяется обобщенным параметром и уточняется лишь при создании конкретного объекта. При объявлении конкретного объекта класса аеас)е компилятор автоматически генерирует все функции и переменные, необходимые лля обработки фактических данных.
В предыдущем примере объявляются по два стека разных типов — целых чисел и действительных чисел. Обратите особое внимание на следующие объявления. зеаги<сцах> з1, з2; // Создаем Лва стека символов. зсасх<ооиЬ1е> оз1, с)з2; // Создаем Лва стека действительных чисел. Как видим, требуемый тип данных задается в угловых скобках.
Изменяя этот тип при создании объекта класса аеас)е, можно изменять тип данных, хранящихся в стеке. Например, используя следующее опрслеление, можно создать другой стек для хране- ния указателей на символы, й аеасх<снах *> спхрех(); Можно создавать стеки, хранящие объекты, тип которых определен пользователем. Допустим, что для хранения информации используется следуюшая структура.
В этом случае класс аеас)с порождает стек, в котором хранятся объекты класса а(Ы. Для эпи о используется следующее объявление. й зсасх<аоот> оЪЗ; Класс веаек демонстрирует, что обобщенные функции и классы являются мощным средством, облегчающим программирование. С его помощью программист может определять общую форму объекта, в котором хранятся данные произвольного типа, и не заботиться об отдельных реализациях классов и функций, предназначенных для разных типов. Компилятор автоматически создаст конкрстныс версии класса. Пример использования двух обобщенных типов данных Шаблонный класс может иметь несколько обобщенных типов. Для этого их следует перечислить в списке шаблонных параметров в объявлении еамр1асе.
Например, следующая программа создаст класс, использующий два обобщенных типа. Глава 18. Шаблоны зсхисе свах снах снах. снах снах а<Ых ( пате(402; зехеес(40); сз.су(30); зсасе[З]; х1р(12): Пример класса, использусщего два обобыенных тиПа. агпс1ице <ъовегеап> цз1гд папеврасе вег); сеьтр1асе <с1авв Туре1, с1авв Туре2> с1азз пус1авв Туре1 1; туре2 3; риЬ11с: пус1аве(туре1 а, Туре2 Ь) ( 1 = а; 3 = Ь; тоЫ впон!) ( соцс « 1 « ' « 3 « 'хп'; ) ): 1пс пазпО ( пус1авв<ъпе, ооиЪ1е> оЬ1(10, 0.23); пус1авв<спат, спал *> оЬ2('Х', "Шаблоны — мопный механизм.") оЬ1.впои(); // Выводим целое и действительное число. оЬ2.впон(); // Выводим символ и указатель на символ.
гесигп 0; ) Эта программа выводит следующие результаты. 10 0.23 Х Л)солоны †мопн механизм. В программе объявляются обьскты двух типов. Объект оыъ использует целые идсйствительныс числа. Объект оЬ2 использует символ и указатель на символ. В обоих случаях при создании объектов компилятор автоматически генерирует соответствующие данные и функции. Применение шаблонных классов: обобщенный массив Чтобы проиллюстрировать практические выгоды, которые предоставляют обобщенные классы, рассмотрим способ, который довольно часто применяется.
Как указано в главе 15, оператор "()" можно перегрузить. Это позволяет создавать собственныс реализации массива, в том числе 'безопасныс" массивы, предусматривающие проверку диапазона индексов в хаас выполнения программы. Как извеспю, в языке С++ нет встроенной проверки диапазона индексов, поэтому в ходе выполнения программы индекс может выйти за допустимыс пределы, нс генерируя сообщения об ошибке. Однако, сели создать класс. содержащий массив, и перегрузить операзор "1) ", выход индекса за допусгимыс пределы можно предотвратить.
Комбинируя перегруженный опсразор с шаблонным классом, можно создать обобщенный безопасный массив произвольного типа. Этот тип массива показан в следующей программе. // Пример обобпенного безопасного массива. Кзпс1ице <1овегеап> кзпс1ибе <свеб11Ь> ивъпд оепеврасе всг); сопвс 1пс БХЕЕ - "10; Часть й. Язык С++ сешр1аее <с1авв АТуре> с1авв асуре ( АТуре а [Я12Е] з риЫас: а суре () ( тедхвсег хпс х; бог(х=Оз х<Б1ЕЕз х+<) а[х] АТуре аорегаеох[](хпе з.); ); // Проверка диапазона для объекта аеуре.
Сешр1аее <с1авв АТуре> АТуре ааеуре<АТуре>ззОРЕГаеог[](1пе з.) ( з.г(х<О ][ х> 51ЕЕ-1) соус « " 1пвначение индекса соме « х « " выходит за прелелы допустимого диапазона. 1п"з екхс(1)з ) гесигп а[1]з ) хпе шахп() асуре<хпс> 1лсоЬз // целочисленный массив. аеуре<боиЬ1е> босЬ1еоЬз // Массив действительных чисел. хпе хз соме « "целочисленный массивз бог(х=Оз х<Б1ЕЕз х++) хпеоЬ[х) Хог(1=0з 1<БТЕЕз х><) сосс « 1псоЬ[х] « соус « '1п'з соле « "массив действительных чисел: гол(х=Оз х<ЯХЕЕз х<ъ) с(осЫеоЬ[х] = (боиЫе) х/Зз Ток(з.=О; х<51ЕЕз хн.) соус «боиЫеоЬ[х] « соцс « 'хп'з хпсоЬ[12] = 100; // Генерирует сообщение об ошибке.
гегигп 0; Эта программа реализует обобщенный тип массива и демонстрирует его применение на примере массивов целых и действительных чисел. Попробуйте создать массивы других типов. Как показывает данный пример, обобщенные ктассьз позволяют создавать один вариант кода, о~лаживать его, а затем применять к любому типу данных, нс предусматривая для каждого типа свой вариант. Применение стандартных типов в обобщенных классах В спецификации шаблона обобщенного класса можно использовать стандартные типы.