|
Программирование >> Инициализация объектов класса, структура
----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 в реализации
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |