|
Программирование >> Инициализация объектов класса, структура
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() . Имя параметра разрешено употреблять внутри объявления или определения шаблона. Параметр-тин служит спецификатором тина; его можно использовать точно так же, как спецификатор любого встроенного или пользовательского типа, например в объявлении переменных или в операциях приведения типов. Параметр-константа применяется как константное значение - там, где требуются константные выражения, например для задания размера в объявлении массива или в качестве начального значения элемента перечисления.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |