|
Программирование >> Инициализация объектов класса, структура
тип1 возвращаемого значения и обоих параметров конкретизирован! из шаблона класса Queue extern Queue< complex<double> > foo( Queue< complex<double> > &, Queue< complex<double> > & ); указатель на функцию-член класса, конкретизированного из шаблона Queue bool (Queue<double>::*pmf)() = 0; / / явное приведение 0 к указате на экземпляр Queue допустимо употребление типа обычного класса: Queue<char*> *pqc = static cast< Queue<char*>* > ( 0 ); Объекты типа класса, конкретизированного по шаблону Queue, объявляются и extern Queue<double> eqd; Queue<int> *pqi = new Queue<int>; Queue<int> aqi[1024]; int main() { int ix; if ( ! pqi->is empty() ) ix = pqi->remove(); ... for ( ix = 0; ix < 1024; ++ix ) eqd[ ix ].add( ix ); ... используются так же, как объекты обычных классов: В объявлении и определении шаблона можно ссылаться как на сам шаблон, так и на объявление шаблона функции template <class Type> void bar( Queue<Type> &, ссылается на обобщенный шаблон Queue<double> & ссылается на конкретизированный шаблон конкретизированный по нему класс: Однако вне такого определения употребляются только конкретизированные экземпляры. Например, в теле обычной функции всегда надо задавать фактические аргументы void foo( Queue<int> &qi ) { Queue<int> *pq = &qi; ... шаблона Queue: Queue qs; ошибка: как конкретизируется шаблон? Конкретизированный шаблон класса Queue можно использовать в программе всюду, где class Matrix; Matrix *pm; правильно: определение класса Matrix знать необязательно класс его знать необязательно: void inverse( Matrix & ); тоже правильно Поэтому объявление указателей и ссылок на конкретизированный шаблон класса не приводит к его конкретизации. (Отметим, что в некоторых компиляторах, написанных до принятия стандарта C++, шаблон конкретизируется при первом упоминании имени конкретизированного класса в тексте программы.) Так, в функции foo() объявляются Queue<int> не конкретизируется при таком использовании в foo() void foo( Queue<int> &qi ) { Queue<int> *pqi = &qi; ... указатель и ссылка на Queue<int>, но это не вызывает конкретизации шаблона Queue: Определение класса необходимо знать, когда определяется объект этого типа. В следующем примере определение obj1 ошибочно: чтобы выделить для него память, class Matrix; Matrix obj1; ошибка: класс Matrix не определен class Matrix { ... }; class компилятору необходимо знать размер класса Matrix: Matrix obj2; правильно Таким образом, конкретизация происходит тогда, когда определяется объект класса, конкретизированного по этому шаблону. В следующем примере определение объекта qi приводит к конкретизации шаблона Queue<int>: Queue<int> qi; конкретизируется Queue<int> Определение Queue<int> становится известно компилятору именно в этой точке, которая называется точкой конкретизации данного класса. Если имеется указатель или ссылка на конкретизированный шаблон, то конкретизация также производится в момент обращения к объекту, на который они ссылаются. В определенной выше функции foo() класс Queue<int> конкретизируется в следующих случаях: когда разыменовывается указатель pqi, когда ссылка qi используется для Шаблон класса конкретизируется только тогда, когда имя полученного экземпляра употребляется в контексте, где требуется определение шаблона. Не всегда определение класса должно быть известно. Например, перед объявлением указателей и ссылок на void foo( Queue<int> &qi ) { Queue<int> *pqi = &qi; Queue<int> конкретизируется в результате вызова функции-члена pqi->add( 255 ); ... членам или функциям-членам этого класса: Определение Queue<int> становится известным компилятору еще до вызова функции-члена add() из foo() . Напомним, что в определении шаблона класса Queue есть также ссылка на шаблон template <class Type> class Queue { public: ... private: QueueItem<Type> *front; QueueItem<Type> *back; QueueItem: }; При конкретизации Queue типом int члены front и back становятся указателями на QueueItem<int>. Следовательно, конкретизированный экземпляр Queue<int> ссылается на экземпляр QueueItem, конкретизированный типом int. Но поскольку соответствующие члены являются указателями, то QueueItem<int> конкретизируется лишь в момент их разыменования в функциях-членах класса Queue<int>. Наш класс QueueItem служит вспомогательным средством для реализации класса Queue и не будет непосредственно употребляться в вызывающей программе. Поэтому пользовательская программа способна манипулировать только объектами Queue. Конкретизация шаблона QueueItem происходит лишь в момент конкретизации шаблона класса Queue или его членов. (В следующих разделах мы рассмотрим конкретизации членов шаблона класса.) В зависимости от типов, которыми может конкретизироваться шаблон, при его определении надо учитывать некоторые нюансы. Почему, например, следующее определение конструктора класса QueueItem не подходит для конкретизации общего template <class Type> class QueueItem { public: QueueItem( Type ); неудачное проектное решение вида? получения значения именуемого объекта и когда pqi или qi употребляются для доступа к
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |