Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 99
Текст из файла (страница 99)
8.8. Настраиваемые подпрограммы Повторное использование кода может значительно повысить производительность программного обеспечения, если есть возможность не писать разные подпрограммы, реализующие один и тот же алгоритм лля данных, имеющих разные типы. Например, в этом случае программисту не нужно писать четыре разные подпрограммы сортировки для того, чтобы упорядочить четыре массива, отличающихся друг от друга только типом своих элементов.
376 Глава 8. Подпрограммы Настраиваемая (кепепс), или полнморфная, подпрограмма (ро!ппогрЬ(с зиЬрюйгжп) эазных вызовах получает параметры разных типов. Перегруженные подпрограммы гсдставляют собой разновидность полиморфизма, называемую специальным полимор-изчоч (аг) Ьос ройпзогрЬ]зщ). Функции языка АР(. обеспечивают более общий вид поли.. эпзча.
Вследствие того что в языке АРЬ применяется динамическое связывание, типы .: четров можно не указывать, онн просто связываются с типами соответствующих фак.еских параметров. ]]араметрический полиморфизм обеспечивается подпрограммами с настраиваемым -зззчетром. который используется для описания типов параметров подпрограмчы. И в : .:ке Ас)а.
и в языке С++ в процессе компиляции поддерживается разновидность пара:-, ического полиморфизма. 8.8.1. Настраиваемые подпрограммы в языке Ада В языке Ада параметрический полиморфизм обеспечивается конструкциями. позвог«шимн создавать различные версии программных единиц, получающих параметры -иного типа.
По запросу пользовательской программы компилятор создает, или конст: нрует, экземпляры различных версий подпрограмм. Поскольку все версии подпрогзчмы имеют одно и то же имя, создается иллюзия, что одна подпрограмма при разных з:ювах может обрабатывать данные разного типа. Поскольку программные единицы .-. го вида являются настраиваемыми по своей природе, иногда их называют настраиваемыми компонентвмн (йепелс цп(гз). Этот же механизм можно использовать для того, чтобы позволить вызывающей поэг1грамме в разных ситуациях вызывать разные экземпляры настраиваемой подпро=зччы.
Такой способ полезен при обеспечении функциональности подпрограмм. пере:. взсмых как параметры. Приведенный ниже пример иллюстрирует процедуру, имеющую три настраиваечых -зраметра, что позволяет подпрограмме получать в качестве параметра настраиваечый зссив. Процедура реализует алгоритм обменной сортировки и может работать с любым ° зсснвом, элементы которого имеют числовой тип, используя диапазон индекса поряд° .
вого типа: депекха Суре 1))ОЕХ ТУРЕ Ев (<>); куре ЕЬЕМЕ))Т ТУРЕ зв ркзчекег Суре ЧЕСТОК хв аккау (1НТЕСЕВ ТУРЕ капде <>] оЕ ЕЬЕМЕМТ ТУРЕ; ркоае<Ыке ЯЕЙЕВ1С ЯОВТ(ЫЯТ : зп опк ЧЕСТОВ); ргосес)иге СЕМЕВ1С ЯО)(Т(ЫЯТ : Еп очи ЧЕСТОВ) зв ТЕМР : ЕЬЕМЕМТ ТУРЕ; )>едзп кок ТОР 1п Ь1ЯТ'Г1ВТЯ..1МОЕХ ТУРЕ'РКЕО(~1ЯТ'ЬАЯТ) 1оор Еок ВОТТОМ хп 1МОЕХ ТУРЕ'ЯОСС(ТОР)..ЫЯТ'ЬАЯТ 1оор ЕЕ Ь1ЯТ(ТОР) > Ь1ЯТ(ВОТТОМ) с)зеп ТЕМР := ЫЯТ(ТОР)г Ь1ЯТ := Ь1ЯТ(ВОТТОМ): Ь1ЯТ(ВОТОМ] := ТЕМРг епй 1хг епс( 1оор; -- хок ВОТТОМ 377 8.8.
Настраиваемые подпрограммы впс( 1оорг -- Гок ТОР епй СЕИЕК1С ЯОКТ; Некоторые части этой настраиваемой процедуры могут казаться довольно странными, если вы не знакомы с языком Ааа. Однако понимать все детали синтаксиса в паннам случае не обязательно. Типы массива и его элементов задаются двумя настраиваемыми параметрами данной процедуры, при этом допускается любой тип и диапазон изменения индекса.
Настраиваемая сортировка — не более чем шаблон процедуры. Компилятор не генерирует для этой процедуры никакого кода, и она никак не влияет на выполнение программы, пока не будет создан экземпляр процедуры для некоторого конкретного типа. Экземпляр процедуры создается с помошью оператора.
аналогичного приведенному ниже: ркосегзике 1ИТЕСЕК ЯОКТ Ев пем СЕИЕК1С БОКТ( 1ИОЕХ ТУРЕ => 1ЫТЕСЕК; ЕЬЕМЕЙТ ТУРЕ => 1ИТЕСЕКг УЕСТОК => 1пт АККАУ)г В ответ на этот оператор компилятор создает версию процедуры СЕИЕК1О ЯОКТ с именем 1итЕСЕК Бокт, сортируюшую массивы типа 1НТ АКРАУ, содержаШие элементы типа 1ИТЕСЕК с индексами типа 1ИТЕСЕК. В процедуре СЕИЕК1С ЯОКТ предполагается, что оператор > определен для элементов сортируемого массива. Универсальность процедуры СЕг(ЕК1О ЯОКТ можно усилить, включив в нее функцию сравнения ее настраиваемых параметров.
Напомним, что в языке Ада не допускается передача подпрограмм в качестве параметров других подпрограмм. Для того чтобы обеспечить эту возможность, в языке Ада используются настраиваемые формальные подпрограммы. В таком языке, как Рааса!, подпрограммы могут передаваться как параметры, так что при конкретном вызове некоторой подпрограммы лля вычисления ее результатов можно использовать передаваемую подпрограмму. В языке Ада тот же результат достигается путем разрешения пользователю создавать неограниченное количество экземпляров настраиваемой подпрограммы с разными используемыми подпрограммами. Например, процедуру Тпседгасе, описанную в разделе 8.6, можно написать на языке Ада следуюшим образом: аепвкдс иЕС)з Еипскйоп ГОН(Х: ГЬОАТ) кесикп ГЬОАТ; ркосег1ике 1ЫТЕСКАТЕ (ЬОЫЕКВО: Дп ГЬОАТ; ОРРЕКВР : Еп ГЬОАТ; КЕЯОЬТ : оие ГЬОАТ) Дв ГОМЧАЬ : Г1 ОАТ; )>вада ГОЫЧАЬ := ГОН(ЬОЬ)ЕКВО)) епг1) Создать экземпляр этой процедуры для интегрирования определенной пользователем функции ГОИ1 можно с помошью следуюшего оператора: ркосес$икв 1ИТЕСКАТЕ ГОИ1 Ев пем 1ИТЕСКАТЕ(ГОН => ГОИ1)) а~в Глава В.
Подпрограммы :-ерь процедура 1(ЧТЕЕЕ)( Г()(Ч1 предназначена для интегрирования функции Г())(1. 8.8.2. Настраиваемые подпрограммы в языке С++ !(зстраиваемые функции в языке С~+ называются шаблонными функциями. Шаблон. фу нкции имеют следующий общий вид: сежр1аке <с1авв параметры> определение функции, которая может иметь параметры, являю::тся классами :зблонная функция должна иметь хотя бы один параметр, являюшиИся классом. Каж- - а гакой параметр имеет слелуюший вид: с1авв идентификатор . пример.
рассмотрим шаблонную функцию севр1все <с1авв Туре> ,ре юах(Туре 11гят, Туре яесопс() ( кесцкп Гуляк > яесопг) ? Гсгяк : яесопс(Г .:;сь . уре — это параметр, указывающий тип данных, с которыми работает функция. ° зеьшляры этой шаблонной функции можно создавать для работы с любым типом дан-.- т. зля которого определен оператор >.
Например, экземпляр процедуры для типа зпс - . зчестве параметра может иметь следующий вид: ьпс мах(хпк Гзгяк, 1пк яесопс(] ( кееикп Г1гяк > яесопс) ? йдгяс : яесопс)г Эти действия можно описать в виде макроопределения (макроса). однако в этом слузг оно может работать неправильно, если его параметрами являются выражения, . еюшие побочный эффект. Допустим, что макрос был определен следующим образом: =:ет'пе вах(а, Ь) ( (а) > (Ь) ? (а): (Ь) --.
т макрос является настраиваемым, т.е. он работает с данными любого числового тиОзнако он не всегда действует правильно, если вызывается с параметрами, имеюши,;юбочный эффект, например: гях(х++,у)Г ". приводит к следующему результату: х++) > (у) '. (х++) : (у)) кзый раз, когда значение переменной х больше значения переменной у, значение пе..:ченной х увеличивается дважды. Экземпляры шаблонных функциИ в языке С++ создаются неявно, независимо от того. --. именно указано в вызове функции: ее имя или ее адрес, полученный с помощью опе-.
з ни а. Например, экземпляр шаблонной функции, определенной выше, можно создать ззжзы с помощью следующего фрагмента кода: для параметров типа Тпс и типа спал, .. тветственно: 379 = б. Настраиваемые подпрограммы дпка, Ь, с; сЬаг <1, е, г; с =- вах(а,Ь); Г = вах(с(, е); Ниже приведена версия настраиваемой подпрограммы на языке С++, описанная в разделе 8.8.1. Она немного отличается от предыдущей версии, поскольку индексы массивов в языке С++ должны быть целыми, а их нижней границей является нуль. Севр1аев <с1авв Туре> чоЫ депег1с яогг(Туре 11яг[], Тпг 1ел ( дпс гор, Ьоггов; Туре Гевр) Гог (гор = 0; гор < 1еп - 2; гор++) гог (Ьоссов = Гор + 1; Ьоссов < 1еп — 1) Ьоссов) И (11яс[сор] > 11яс [Ьоссов] ) ( Гевр = 11яс[сор]г 11яс[сор] = 11яс[Ьостов]; 11яг[ьоггов) = геврг //* конец цикла гог ( Ьоггов ) //** конец настраиваемой функции сортировки Ниже приведен пример создания экземпляра этой шаблонной функции: г1оас Т1Г 11Г[100]Г йепегдс яогс(Т1Г 11яс, 100) Настраиваемые подпрограммы на языке Ада н шаблонные функции в языке С++ иллеют отдаленное отношение к подпрограммам, в которых типы формальных параметров при вызове динамически связываются с типами фактических параметров.
В этом случае нужен лишь один экземпляр кода, в то время как подходы, реализованные в языках Ада и С++, требуют создания во время компиляции копии кода для каждого отдельного типа. а связывание вызовов с подпрограммами осуществляется статически. В языках Вша[Вайс, ]ача, Ада 95 и С++ вызовы динамически связываются с нужной версией метода, соответствующего типам фактических параметров. Эта тема обсуждается в главе! 1. 8.9. Равделвная и независимая компиляция Возможность компилировать части программы без компиляции всей программы существенна при создании больших систем программного обеспечения. Следовательно, языки.