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

1 ... 167 168 169 [ 170 ] 171 172 173 ... 395


----user.h----class SmallInt { /* ... */ } void print( const SmallInt & );

----user.C----

#include <primer.h> #include user.h

SmallInt asi[4];

int main() {

задать значения элементов массива asi

конкретизируется min( SmallInt*, int ) int size = sizeof(asi) / sizeof(Smalllnt); min( &asi[0], size );

Это нормально: м1 хотим, чтобы учит1валась именно наша функция print(const Smialllnt &). Рассмотрения функций, определенных в библиотеке <primer.h>, недостаточно. Второй шаг разрешения имени гарантирует, что если имя, использованное в определении, зависит от параметров шаблона, то принимаются во внимание имена, объявленные в контексте конкретизации. Поэтому можно быть уверенным, что функции, умеющие манипулировать объектами типа SmallInt, попадут в поле зрения компилятора при анализе шаблона, которому в качестве аргумента передан тип SmallInt.

Место в программе, где происходит конкретизация шаблона, называется точкой конкретизации. Знание этой точки важно потому, что она определяет, какие объявления учитывает компилятор для имен, зависящих от параметров шаблона. Такая точка всегда находится в области видимости пространства имен и следует за функцией, внутри которой произошла конкретизация. Например, точка конкретизации min(SmallInt*,int) расположена сразу после функции main() в области видимости

...

int main() {

...

использование min(SmallInt*,int) min( &asi[0], size );

точка конкретизации min(SmallInt*,int)

как будто объявление конкретизированной функции влядит так: SmallInt min( SmallInt* array, int size )

пространства имен:

{ /* ... */ }

Но что, если конкретизация шаблона случается в одном исходном файле несколько раз? Где тогда будет точка конкретизации? Вы можете спросить: А какая, собственно, разница? В нашем примере для SmallInt разница есть, поскольку объявление функции print(const SmallInt &) должно появиться перед точкой конкретизации min(SmallInt*,int) :



#include <primer.h> void another();

SmallInt asi[4];

int main() {

задать значения элементов массива asi int size = sizeof(asi) / sizeof(Smalllnt); min( &asi[0], size );

another();

...

точка конкретизации здесь?

void another() {

int size = sizeof(asi) / sizeof(Smalllnt); min( &asi[0], size );

или здесь?

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

#include <primer.h>

user.h содержит объявления, необходимхе при конкретизации #include user.h void another();

SmallInt asi[4];

int main() {

...

первая точка конкретизации min(SmallInt*,int) void another() {

...

включается перед любой возможной конкретизацией шаблона:

вторая точка конкретизации min(SmallInt*,int)

А если конкретизация шаблона происходит в нескольких файлах? Например, что будет, если функция another() находится в другом файле, нежели main() ? Тогда точка конкретизации есть в каждом файле, где используется конкретизированная из шаблона функция. Компилятор свободен в выборе любой из них, так что нам снова придется проявить аккуратность и включить файл user.h во все исходные файлы, где используются конкретизированные функции. Тем самым гарантируется, что реализация min(SmallInt*,int) будет ссылаться именно на нашу функцию print(const SmallInt &) вне зависимости от того, какую из точек конкретизации выберет компилятор.



----exercise.h----d display( const voi typedef

void display( const void* ); typedef unsigned int SIZE;

template <typename Type>

Type max( Type* array, SIZE size )

Type max val = array[0]; for ( SIZE i = 1; i < size; ++i ) if ( array[i] > max val ) max val = array[i];

display( Iaximum value found: ); display( max val );

return max val;

----user.h----class LongDouble { /* ... */ }; void display( const LongDouble & ); void display( const char * ); typedef int SIZE;

----user.C----

#include <exercize.h

#include user.h

LongDouble ad[7];

int main() {

задать значения элементов массива ad

конкретизируется max( LongDouble*, SIZE SIZE size = sizeof(ad) / sizeof(LongDouble),

max( &ad[0], size );

max(LongDouble*,SIZE) ?

10.10. Пространства имен и шаблоны функций А

Как и любое другое глобальное определение, шаблон функции может быть помещен в пространство имен (см. обсуждение пространств имен в разделах 8.5 и 8.6). Mi получили бы ту же семантику, если бы определили шаблон в глобальной области видимости, скрыв его имя внутри пространства имен. При использовании вне этого пространства необходимо либо квалифицировать имя шаблона именем пространства имен, либо использовать using-объявление:

Упражнение 10.13

Назовите два шага разрешения имени в определениях шаблона. Объясните, каким образом первый шаг отвечает потребностям разработчика библиотеки, а второй обеспечивает гибкость, необходимую пользователям шаблонов.

Упражнение 10.14

На какие объявления ссылаются имена display и SIZE в реализации



1 ... 167 168 169 [ 170 ] 171 172 173 ... 395

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