|
Программирование >> Операторы преобразования типа
В первой строке Т определяется как произвольный тип данных, который должен передаваться при вызове функции, В качестве имени параметра может использоваться произвольный идентификатор, но имя Т встречается настолько часто, что почти стало стандартным обозначением. Хотя перед формальным параметром шаблона стоит ключевое слово class , он вовсе не обязан быть классом. Допускается любой тип данных, который поддерживает операции, используемые шаблоном. По тому же принципу классы параметризуются для произвольных типов. Параметризация особенно удобна для контейнерных классов, поскольку она позволяет определять операции с элементами контейнера для произвольного типа элементов. Стандартная библиотека С++ содержит многочисленные шаблоны контейнеров (за примерами обращайтесь к главам 6 и 10). Впрочем, шаблоны используются и для других целей. Например, строковые классы параметризуются по типу символов и свойствам кодировки (см. главу И), Не стоит полагать, что шаблон компилируется только один раз, а в результате компиляции строится код, подходящий для любого типа. В действительности шаблон компилируется для каждого типа или комбинации типов, с которыми он используется. Отсюда следует важная проблема, связанная с практическим применением шаблонов; реализация шаблонной функции должна быть доступна к моменту вызова, чтобы функцию можно было откомпилировать для конкретного типа. Следовательно, в настоящее время единственный переносимый способ использования шаблонов основан на их определении в заголовочных файлах с применением подставляемых (inline) функций. Полноценная реализация стандартной библиотеки С++ должна поддерживать не только шаблоны, но и многие стандартизированные свойства шаблонов. Некоторые из этих свойств рассматриваются ниже. Нетипизованные параметры шаблонов Кроме параметров-типов в шаблонах допускается использование нетипизованных параметров. В этом случае нетипизованный параметр считается частью определения типа. Например, аргумент шаблона стандартного класса bitseto (см. с. 444) содержит количество битов. В следующем фрагменте определяются два битовых поля, состоящих из 32 и 50 бит: b1tset<32> flags32: Битовое поле из 32 бит bitset<50> flagsSO; Битовое поле из 50 бит Эти битовые поля относятся к разным типам, потому что при их определении задаются разные аргументы шаблонов. Следовательно, их нельзя присваи- Ютючевое слово class было выбрано для того, чтобы избежать введения нового ключевого слова при использовании шаблонов. Тем не менее в современной версии С++ появилось новое ключевое слово typename, которое также может использоваться при объявлении шаблонов (см. с. 27). Для решения проблемы с обязательным определением шаблонов в заголовочных файлах в стандарт была включена модель компиляции шаблонов с ключевым словом export. Впрочем, на момент написания книги она еще нигде не была реализована. вать или сравнивать друг с другом (при отсутствии соответствующего преобразования типа). Параметры шаблонов по умолчанию Шаблоны классов могут иметь параметры по умолчанию. Например, следующий фрагмент разрешает объявлять объекты класса MyClass как с одним, так и с двумя аргументами: template <class Т. class container = vector<T> > class MyClass; При передаче одного аргумента вместо второго используется параметр по умолчанию: HyClass<int> xl; Эквивалентно MyClass<1nt.vector<1nt> > Аргументы шаблонов по умолчанию могут определяться на основе предыдущих аргументов. Ключевое слово typename Ключевое слово typename означает, что следующий за ним идентификатор обозначает тип. Рассмотрим следуюншй пример; template <class Т> class MyClass { typename Т::SubType * ptr; В этом фрагменте ключевое слово typename поясняет, что SubType является подтипом класса Т, Следовательно, ptr - указатель на тип T::SubType. Без typename идентификатор SubType интерпретируется как статический член класса, а следующая строка воспринимается как умножение значения SubType типа Т на ptr: Т::SubType * ptr Поскольку идентификатор SubType объявлен типом, любой тип, используемый вместо Т, должен содержать внутренний тип SubType. Например, испо-льзо-вание типа Q в качестве аргумента шаблона, как показано ниже, возможно то./1ь-ко при условии, что в Q определяется внутренний тип SubType: HyClass<Q> х; Объявление выглядит примерно так: class Q { typedef 1nt SubType; * Обратите внимание на пробел между символами >. Последовательность > воспринимается компилятором как оператор сдвига, что приводит к синтаксической ошибке. В этом случае переменная ptr класса MyClass<Q> является указателем на тип int. Однако подтип также может быть абстрактным типом данных (например, классом): class Q { class SubType: Ключевое слово typename всегда должно квалифицировать идентификатор шаблона как тип, даже если другая интерпретация не имеет смысла. В С++ любой идентификатор шаблона, указанный без ключевого слова typename, интерпретируется как значение. Ключевое слово typename также может использоваться вместо слова class в объявлении шаблона: template <typename Т> class MyClass: Шаблонные функции классов Допускается определение функций классов в виде шаблонов, С другой стороны, такие функции не могут быть виртуальными и не имеют параметров по умолчанию. Пример: class MyClass { template <class Т> void f(T): Шаблон MyClass:f объявляет набор функций с параметром произвольного типа. При вызове функции может передаваться любой аргумент (при условии, что его тип поддерживает все операции, используемые в f). Данная возможность часто используется для автоматического преобразования типов в классах шаблонов. Например, в следующем определении аргумент х функции assignO должен точно соответствовать типу объекта, для которого он вызывается: template <class Т> class MyClass { private: Т value; public; void assign ( const MyClass<T>& x) { Тип x должен соответствовать типу *th1s value = X.value; Однако использование шаблона с другим типом при вызове assign() является ошибкой даже в том случае, если между типами выполняется автоматическое преобразование:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |