Программирование >>  Инициализация объектов класса, структура 

1 ... 153 154 155 [ 156 ] 157 158 159 ... 395


min( 10, 20 ); min( 10.0, 20.0 );

но может преподнести сюрпризы в более сложных случаях: такой механизм ведет себя не как вызов функции, он лишь выполняет текстовую подстановку аргументов. В результате значения обоих аргументов оцениваются дважды:: один раз при сравнении a и b, а

#include <iostream>

#define min(a,b) ((a) < (b) ? (a) : (b))

const int size = 10; int ia [size];

int main() {

int elem cnt = 0; int *p =&ia[0];

подсчитать число элементов массива while ( min(p++,&ia[size]) != &ia[size] )

++elem cnt;

cout << elem cnt : << elem cnt

<< \texpecting: << size << endl; return 0;

второй - при вычислении возвращаемого макросом результата:

На первый взгляд, эта программа подсчитывает количество элементов в массиве ia целых чисел. Но в этом случае макрос miin() расширяется неверно, поскольку операция постинкремента применяется к аргументу-указателю дважды при каждой подстановке. В результате программа печатает строку, свидетельствующую о неправильных вычислениях:

elem cnt : 5 expecting: 10

Шаблоны функций предоставляют в наше распоряжение механизм, с помощью которого можно сохранить семантику определений и вызовов функций (инкапсуляция фрагмента кода в одном месте программы и гарантированно однократное вычисление аргументов), не принося в жертву сильную типизацию яз1ка C++, как в случае применения макросов.

Шаблон дает алгоритм, используемый для автоматической генерации экземпляров функций с различными тинами. Программист параметризует все или только некоторые тины в интерфейсе функции (т.е. тины формальных параметров и возвращаемого значения), оставляя ее тело неизменным. Функция хорошо подходит на роль шаблона, если ее реализация остается инвариантной на некотором множестве экземпляров, различающихся типами данных, как, скажем, в случае min() .

Так определяется шаблон функции min() :



template <class Type>

Type min2( Type a, Type b ) { return a < b ? a : b;

int main() {

правильно: min( int, int ); min( 10, 20 );

правильно: min( double, double ); min( 10.0, 20.0 );

return 0;

Если вместо макроса препроцессора miin() подставить в текст пред1дущей программа: этот шаблон, то результат будет правильным:

elem cnt : 10 expecting: 10

(В стандартной библиотеке C++ есть шаблоны функций для многих часто используемых алгоритмов, например для miin(). Эти алгоритма: описываются в главе 12. А в данной вводной главе мы приводим собственные упрощенные версии некоторых алгоритмов из стандартной библиотеки.)

Как объявление, так и определение шаблона функции всегда должны начинаться с ключевого слова template, за которым следует список разделенных запятыми идентификаторов, заключенный в угловые скобки < и >, - список параметров шаблона, обязательно непустой. У шаблона могут быть параметры-типы, представляющие некоторый тип, и параметры-константы, представляющие фиксированное константное выражение.

Параметр-тип состоит из ключевого слова class или ключевого слова typename, за которым следует идентификатор. Эти слова всегда обозначают, что последующее имя относится к встроенному или определенному пользователем типу. Имя параметра шаблона выбирает программист. В приведенном примере мы использовали имя Type, но

template <class Glorp>

Glorp min2( Glorp a, Glorp b ) { return a < b ? a : b;

могли выбрать и любое другое:

При конкретизации (порождении конкретного экземпляра) шаблона вместо параметра-типа подставляется фактический встроенный или определенный пользователем тип. Любой из типов int, double, char*, vector<int> или list<double> является допустимым аргументом шаблона.

Параметр-константа выглядит как обычное объявление. Он говорит о том, что вместо имени параметра должно быть подставлено значение константы из определения шаблона. Например, size - это параметр-константа, который представляет размер массива arr:



template <class Type, int size> Type min( Type (&arr) [size] );

Вслед за списком параметров шаблона идет объявление или определение функции. Если не обращать внимания на присутствие параметров в виде спецификаторов типа или констант, то определение шаблона функции выглядит точно так же, как и для обычных

template <class Type, int size> Type min( const Type (&r array)[size] ) {

/* параметризованная функция для отыскания

* минимального значения в массиве */ Type min val = r array[0]; for ( int i = 1; i < size; ++i ) if ( r array[i] < min val ) min val = r array[i];

return min val;

функций:

В этом примере Type определяет тип значения, возвращаемого функцией min() , тип параметра r array и тин локальной неременной miin val; size задает размер массива r array. В ходе работы программы при использовании функции min() вместо Type могут быть подставлены любые встроенные и определенные пользователем типы, а вместо size - те или иные константные выражения. (Напомним, что работать с функцией можно двояко: вызвать ее или взять ее адрес).

Процесс подстановки типов и значений вместо параметров называется конкретизацией шаблона. (Подробнее мы остановимся на этом в следующем разделе.)

Список параметров нашей функции min() может показаться чересчур коротким. Как было сказано в разделе 7.3, когда параметром является массив, передается указатель на его первый элемент, первая же размерность фактического аргумента-массива внутри определения функции неизвестна. Чтобы обойти эту трудность, мы объявили первый параметр min() как ссылку на массив, а второй - как его размер. Недостаток подобного подхода в том, что при использовании шаблона с массивами одного и того же типа int, но разных размеров генерируются (или конкретизируются) различные экземпляры функции min() .

Имя параметра разрешено употреблять внутри объявления или определения шаблона. Параметр-тин служит спецификатором тина; его можно использовать точно так же, как спецификатор любого встроенного или пользовательского типа, например в объявлении переменных или в операциях приведения типов. Параметр-константа применяется как константное значение - там, где требуются константные выражения, например для задания размера в объявлении массива или в качестве начального значения элемента перечисления.



1 ... 153 154 155 [ 156 ] 157 158 159 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика