|
Программирование >> Инициализация объектов класса, структура
template <class Type> class QueueItem { ... public: потенциально неэффективно QueueItem( const Type &t ) { item = t; next = 0; QueueItem, нет ассоциированного конструктора: Если аргументом шаблона является тип класса с конструктором (например, string), то item инициализируется дважды:! Конструктор по умолчанию string вызывается для инициализации item перед выполнением тела конструктора QueueItem. Затем для созданного объекта item производится почленное присваивание. Избежать такого можно с помощью явной инициализации item в списке инициализации членов внутри template <class Type> class QueueItem { ... public: item инициализируется в списке инициализации членов конструктора QueueItem( const Type &t ) : item(t) { next = 0; } определения конструктора QueueItem: }; (Списки инициализации членов и основания для их применения обсуждались в разделе 14.5.) 16.2.1. Аргументы шаблона для параметров-констант Параметр шаблона класса может и не быть типом. На аргументы, подставляемые вместо таких параметров, накладываются некоторые ограничения. В следующем примере мы изменяем определение класса Screen (см. главу 13) на шаблон, параметризованный высотой и шириной: В данном определении аргумент передается по значению. Это допустимо, если QueueItem конкретизируется встроенным типом (например, QueueItem<int>). Но если такая конкретизация производится для объемного типа (скажем, Matrix), то накладные расходы, вызванные неправильным выбором на этапе проектирования, становятся неприемлем1ми. (В разделе 7.3 обсуждались вопросы производительности, связанн1е с передачей параметров по значению и по ссылке.) Поэтому аргумент конструктора объявляется как ссылка на константный тип: QueueItem( const Type & ); Следующее определение приемлемо, если у типа, для которого конкретизируется template <int hi, int wid> class Screen { public: Screen() : height( hi ), width( wid ), cursor ( 0 ), screen( hi * wid, # ) { } ... private: string screen; string::size type cursor; short height; short width; typedef Screen<24,80> termScreen; termScreen hp2621; Screen<8,24> ancientScreen; Выражение, с которым связан параметр, не являющийся типом, должно быть константным, т. е. вычисляемым во время компиляции. В примере выше typedef termScreen ссылается на экземпляр шаблона Screen<24,80>, где аргумент шаблона для hi равен 24, а для wid - 80. В обоих случаях аргумент - это константное выражение. Однако для шаблона BufPtr конкретизация приводит к ошибке, так как значение указателя, получающееся при вызове оператора new() , становится известно только во template <int *ptr> class BufPtr { ... }; ошибка: аргумент шаблона нельзя вгчисть во время компиляции время выполнения: BufPtr< new int[24] > bp; Не является константным выражением и значение неконстантного объекта. Его нельзя использовать в качестве аргумента для параметра-константы шаблона. Однако адрес любого объекта в области видимости пространства имен, в отличие от адреса локального объекта, является константным выражением (даже если спецификатор const отсутствует), поэтому его можно применять в качестве аргумента для параметра- template <int size> Buf { ... }; template <int *ptr> class BufPtr { ... }; int size val = 1024; const int c size val = 1024; Buf< 1024 > buf0; правильно Buf< c size val > buf1; правильно Buf< sizeof(size val) > buf2; правильно: sizeof(int) BufPtr< &size val > bp0; правильно ошибка: нельзя вычислить во время компиляции константы. Константным выражением будет и значение оператора sizeof: Buf< size val > buf3; template < class Type, int size > class FixedArray { public: FixedArray( Type *ar ) : count( size ) { for ( int ix = 0; ix < size; ++ix ) array[ ix ] = ar[ ix ]; private: Type array[ size ]; int count; int ia[4] = { 0, 1, 2, 3 }; аргумента для задания значения этого параметра: FixedArray< int, sizeof( is ) / sizeof( int ) > ia ); Выражения с одинаковыми значениями считаются эквивалентными аргументами для параметров-констант шаблона. Так, все три экземпляра Screen ссылаются на один и тот const int width = 24; const int height = 80; все это Screen< 24, 80 > Screen< 2*12, 40*2 > scr0; Screen< 6+6+6+6, 20*2 + 40 > scr1; же конкретизированный из шаблона класс Screen<24,80>: Screen< width, height > scr2; Между типом аргумента шаблона и типом параметра-константы допустимы некоторые преобразования. Их множество является подмножеством преобразований, допустимых для аргументов функции: трансформации l-значений, включающие преобразование 1-значения в г- template <int *ptr> class BufPtr { ... }; int array[10]; значение, массива в указатель и функции в указатель: BufPtr< array > bpObj; преобразование массива в указатель template <const int *ptr> class Ptr { ... }; int iObj; преобразования квалификаторов: Вот еще один пример, иллюстрирующий использование параметра-константы для представления константного значения в определении шаблона, а также применение его
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |