|
Программирование >> Инициализация объектов класса, структура
---- primer.h ---- это объявление необходимо: внутри min() вызывается print( const char * ) void print( const char * ); template <typename Type> Type min( Type* array, int size ) { ... print( Minimum value found: print( min val ); return min val; поместить объявление print() перед определением min() : С другой стороны, объявление функции print() , используемой для печати min val, пока не нужно, так как еще неизвестно, какую конкретно функцию надо искать. Мы не знаем, какая функция print() будет вызвана при обращении print(min val) , пока тип min val не станет известным. size останется int при любом типе параметра шаблона. Следовательно, типы array и min val в разных конкретизациях различны. Поэтому мы говорим, что типы этих переменных зависят от параметра шаблона, тогда как тип size от него не зависит. Так как тип min val неизвестен, то неизвестна и операция, которая будет использоваться при появлении min val в выражении. Например, какая функция print() будет вызвана при обращении print(miin val) ? С типом аргумента int? Или float? Будет ли вызов ошибочным, поскольку не существует функции, которая может быть вызвана с аргументом того же типа, что и min val? Принимая все это во внимание, мы говорим, что и вызов print(min val) зависит от параметра шаблона. Такие вопросы не возникают для тех конструкций внутри min() , которые не зависят от параметров шаблона. Например, всегда известно, какая функция должна быть вызвана для print( Minimium value found: ). Это функция печати строк символов. В данном случае print() остается одной и той же при любой конкретизации шаблона, то есть не зависит от его параметров. В главе 7 м1 видели, что в C++ функция должна быть объявлена до ее вызова. Нужно ли объявлять функцию, вызываемую внутри шаблона, до того, как компилятор увидит его определение? Должны ли мы объявить функцию print() в предыдущем примере до определения шаблона min() ? Ответ зависит от особенностей имени, на которое мы ссылаемся. Конструкцию, не зависящую от параметров шаблона, следует объявить перед ее использованием в шаблоне. Представленное выше определение шаблона функции min() некорректно. Поскольку вызов print( Minimum value found: ); не зависит от параметров шаблона, то функция print() для печати строк символов должна быть объявлена до использования. Чтобы исправить эту ошибку, можно int main() int size = sizeof(ai) / sizeof(int); конкретизируется min( int*, int ) min( &ai [0], size ); print(min val) ? До конкретизации шаблона. Например: main() вызывает конкретизированную из шаблона функцию min(int*,int) . В этой реализации Type заменено int, и тип переменной min val, следовательно, равен int. Поэтому при обращении print(min val) вызывается функция с аргументом типа int. Именно тогда, когда конкретизируется min(int*,int) , становится известно, что при втором вызове аргумент print() имеет тип int. В этот момент такая функция должна быть видима. Если бы функция print(int) не была объявлена до конкретизации min(int*,int) , то компилятор выдал бы сообщение об ошибке. Поэтому разрешение имен в определении шаблона происходит в два этапа. Сначала разрешаются имена, не зависящие от его параметров, а затем, при конкретизации, -имена, зависящие от параметров. Но зачем нужны два шага? Почему бы, например, не разрешать все имена при конкретизации? Если вы проектируете шаблон функции, то, вероятно, хотели бы сохранить контроль над тем, когда разрешаются имена в его определении. Предположим, что шаблон min() - это часть библиотеки, в которой определены и другие шаблоны и функции. Желательно, чтобы реализации min() по возможности использовали другие компоненты нашей же библиотеки. В предыдущем примере интерфейс библиотеки определен в заголовочном файле <primer.h>. Как объявление функции print(const char*) , так и определение функции min() являются частями интерфейса. Mi хотим, чтобы конкретизации шаблона min() пользовались функцией print() из нашей библиотеки. Первый этап разрешения имени это гарантирует. Если имя, использованное в определении шаблона, не зависит от его параметров, то оно обязательно будет относиться к компоненту внутри библиотеки, т.е. к тому объявлению, которое включено в один пакет с этим определением в заголовочном файле <primer.h>. На самом деле автор шаблона должен позаботиться о том, чтобы были объявлены все имена, использованные в определениях и не зависящие от параметров. Если этого нет, то определение шаблона вызовет ошибку. При конкретизации шаблона компилятор ее не исправляет: Когда же должна быть объявлена функция print(), вызываемая при обращении #include <primer.h> void print( int ); int ai[4] = {12, 8, 73, 45 }; ----primer.h----template <typename Type> Type min( Type* array, int size ) Type min val = array[0]; ... ошибка: функция print( const char* ) не найдена print( Minimum value found: ); правильно: зависит от параметра шаблона print( min val ); ... ----user.C---- #include <primer.h> это объявление print( const char* ) игнорируется void print( const char* ); void print( int ); int ai[4] = {12, 8, 73, 45 }; int main() int size = sizeof(ai) / sizeof(int); конкретизируется min( int*, int ) min( &ai[0], size ); Объявление функции print( const char* ) в файле user.C невидимо в том месте, где появляется определение шаблона. Однако оно видимо там, где конкретизируется шаблон min(int*,int) , но это объявление не рассматривается при компиляции вызова print( Minimum value found: ) , так как последний не зависит от параметров шаблона. Если некоторая конструкция в определении шаблона не зависит от его параметров, то имена разрешаются в контексте самого определения, и результат разрешения в дальнейшем не пересматривается. Поэтому на программиста возлагается ответственность за то, чтобы объявления имен, встречающихся в определении, были включены в интерфейс библиотеки вместе с шаблоном. А теперь предположим, что библиотека была написана кем-то другим, а м1 ее пользователи, которым доступен интерфейс, определенный в заголовочном файле <primer.h>. Иногда нужно, чтобы объекты и функции, определенные в нашей программе, учитывались при конкретизации шаблона из библиотеки. Допустим, мы определили в своей программе класс Smialllnt и хотели бы конкретизировать функцию min() из библиотеки <primer.h> для получения минимального значения в массиве объектов типа Smialllnt. При конкретизации шаблона miin() для массива объектов типа SmallInt вместо аргумента шаблона Type подставляется тип Smialllnt. Следовательно, miin val в конкретизированной функции min() имеет тот же тип. Тогда как разрешится вызов функции print(min val) ?
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |