16.3. Функции-члены шаблонов классов

16.3. Функции-члены шаблонов классов

Как и для обычных классов, функция-член шаблона класса может быть определена либо внутри определения шаблона (и тогда называется встроенной), либо вне его. Мы уже встречались со встроенными функциями-членами при рассмотрении шаблона Queue. Например, конструктор Queue является встроенным, так как определен внутри определения шаблона класса:

template class Type

class Queue {

// ...

public:

// встроенный конструктор

Queue() : front( 0 ), back( 0 ) { }

// ...

};

При определении функции-члена шаблона вне определения самого шаблона следует применять специальный синтаксис для обозначения того, членом какого именно шаблона является функция. Определению функции-члена должно предшествовать ключевое слово template, за которым следуют параметры шаблона. Так, конструктор Queue можно определить следующим образом:

template class Type

class Queue {

public:

Queue();

private:

// ...

};

template class Type

inline Queue Type ::

Queue( ) { front = back = 0; }

За первым вхождением Queue (перед оператором ::) следует список параметров, показывающий, какому шаблону принадлежит данная функция-член. Второе вхождение Queue в определение конструктора (после оператора ::) содержит имя функции-члена, за которым может следовать список параметров шаблона, хотя это и необязательно. После имени функции идет ее определение;. в нем могут быть ссылки на параметр шаблона Type всюду, где в определении обычной функции использовалось бы имя типа.

Функция-член шаблона класса сама является шаблоном. Стандарт C++ требует, чтобы она конкретизировалась только при вызове либо при взятии ее адреса. (Некоторые более старые компиляторы конкретизируют такие функции одновременно с конкретизацией самого шаблона класса.) При конкретизации функции-члена используется тип того объекта, для которого функция вызвана:

Queue string qs;

Объект qs имеет тип Queue string . При инициализации объекта этого класса вызывается конструктор Queuestring. В данном случае аргументом, которым конкретизируется функция-член (конструктор), будет string.

Функция-член шаблона конкретизируется только при реальном использовании в программе (т.е. при вызове или взятии ее адреса). От того, в какой именно момент конкретизируется функция-член, зависит разрешение имен в ее определении (см. раздел 16.11) и объявление ее специализации (см. раздел 16.9).

16.3.1. Функции-члены шаблонов Queue и QueueItem

Чтобы понять, как определяются и используются функции-члены шаблонов классов, продолжим изучение шаблонов Queue и QueueItem:

template class Type

class Queue {

public:

Queue() : front( 0 ), back ( 0 ) { }

~Queue();

Type& remove();

void add( const Type & );

bool is_empty() const {

return front == 0;

}

private:

QueueItem Type *front;

QueueItem Type *back;

};

Деструктор, а также функции-члены remove() и add() определены не в теле шаблона, а вне его. Деструктор Queue опустошает очередь:

template class Type

Queue Type ::~Queue()

{

while (! is_empty() )

remove();

}

Функция-член Queue Type ::add() помещает новый элемент в конец очереди:

template class Type

void Queue Type ::add( const Type &val )

{

// создать новый объект QueueItem

QueueItem Type *pt =

new QueueItem Type ( val );

if ( is_empty() )

front = back = pt;

else

{

back- next = pt;

back = pt;

}

}

Функция-член Queue Type ::remove() возвращает значение элемента, находящегося в начале очереди, и удаляет сам элемент.

#include iostream

#include cstdlib

template class Type

Type Queue Type ::remove()

{

if ( is_empty() )

{

cerr "remove() вызвана для пустой очереди ";

exit( -1 );

}

QueueItem Type *pt = front;

front = front- next;

Type retval = pt- item;

delete pt;

return retval;

}

Мы поместили определения функций-членов в заголовочный файл Queue.h, включив его в каждый файл, где возможны конкретизации функций. (Обоснование этого решения, а также рассмотрение более общих вопросов, касающихся модели компиляции шаблонов, мы отложим до раздела 16.8.)

В следующей программе иллюстрируется использование и конкретизация функции-члена шаблона Queue:

#include iostream

#include "Queue.h"

int main()

{

// конкретизируется класс Queue int

// оператор new требует, чтобы Queue int был определен

Queue int *p_qi = new Queue int ;

int ival;

for ( ival = 0; ival 10; ++ival )

// конкретизируется функция-член add()

p_qi- add( ival );

int err_cnt = 0;

for ( ival = 0; ival 10; ++ival ) {

// конкретизируется функция-член remove()

int qval = p_qi- remove();

if ( ival != qval ) err_cnt++;

}

if ( !err_cnt )

cout "!! queue executed ok ";

else cerr "?? queue errors: " err_cnt endl;

return 0;

}

После компиляции и запуска программа выводит следующую строку:

!! queue executed ok

Упражнение 16.5

Используя шаблон класса Screen, определенный в разделе 16.2, реализуйте функции-члены Screen (см. разделы 13.3, 13.4 и 13.6) в виде функций-членов шаблона.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

5.2.1 Функции Члены

Из книги C++ автора Хилл Мюррей

5.2.1 Функции Члены Рассмотрим реализацию понятия даты с использованием struct для того, чтобы определить представление даты date и множества функций для работы с переменными этого типа:struct date (* int month, day, year; *); // дата: месяц, день, год *) date today; void set_date(date*, int, int, int); void next_date(date*); void


7.2.2 Функции Члены

Из книги Как функции, не являющиеся методами, улучшают инкапсуляцию автора Мейерс Скотт

7.2.2 Функции Члены Просто структуры данных вроде employee и manager на смом деле не столь интересны и часто не особенно полезны, потому рассмотрим, как добавить в них функции. Например:class employee (* char* name; // ... public: employee* next; void print(); // ... *);class manager : public employee (* // ... public: void print(); // ... *);Надо


8.5.2 Функции Члены

Из книги Справочное руководство по C++ автора Страустрап Бьярн

8.5.2 Функции Члены Функция, описанная как член, (без спецификатора friend (#8.5.10)) называется функцией членом и вызывается с исползованием синтаксиса члена класса (#7.1). Например:struct tnode (* char tword[20]; int count; tnode *left; tnode *right; void set (char* w,tnode* l,tnode* r); *);tnode n1, n2; n1.set («asdf», amp;n2,0); n2.set


Инкапсуляция и функции – не члены

Из книги C++ для начинающих автора Липпман Стенли

Инкапсуляция и функции – не члены Мы теперь видим, что приемлемый способом оценки инкапсуляции является количество функций, которые могли бы быть разрушены, если изменяется реализация класса. В этом случае становится ясно, что класс с n методами более инкапсулирован, чем


R.9.3 Функции-члены

Из книги автора

R.9.3 Функции-члены Функция, описанная как член (без спецификации friend §R.11.4), называется функция-член и вызывается в соответствии с синтаксисом члена класса (§R.5.2.4), например:struct tnode { char tword[20]; int count; tnode *left; tnode *right; void set(char*, tnode* l, tnode *r);};Здесь set является функцией-членом и может


R.14.6 Функции-члены шаблонов типа

Из книги автора

R.14.6 Функции-члены шаблонов типа Функция-член шаблонного класса считается неявной шаблонной функцией, а параметры шаблона типа для ее класса - ее шаблонными параметрами. Приведем пример, в котором описаны три шаблона типа для функции:template‹class T› class vector { T* v; int


13.1.2. Функции-члены

Из книги автора

13.1.2. Функции-члены Пользователям, по-видимому, понадобится широкий набор операций над объектами типа Screen: возможность перемещать курсор, проверять и устанавливать области экрана и рассчитывать его реальные размеры во время выполнения, а также копировать один объект в


13.3. Функции-члены класса

Из книги автора

13.3. Функции-члены класса Функции-члены реализуют набор операций, применимых к объектам класса. Например, для Screen такой набор состоит из следующих объявленных в нем функций-членов:class Screen {public:void home() { _cursor = 0; }char get() { return _screen[_cursor]; }char get( int, int );void move( int, int );bool checkRange( int, int );int


13.5.1. Статические функции-члены

Из книги автора

13.5.1. Статические функции-члены Функции-члены raiseInterest() и interest() обращаются к глобальному статическому члену _interestRate:class Account {public:void raiseInterest( double incr );double interest() { return _interestRate; }private:static double _interestRate;};inline void Account::raiseInterest( double incr ){_interestRate += incr;}Проблема в том, что любая функция-член


16.1.1. Определения шаблонов классов Queue и QueueItem

Из книги автора

16.1.1. Определения шаблонов классов Queue и QueueItem Ниже представлено определение шаблона класса Queue. Оно помещено в заголовочный файл Queue.h вместе с определением шаблона QueueItem:#ifndef QUEUE_H#define QUEUE_H// объявление QueueItemtemplate class T class QueueItem;template class Typeclass Queue {public:Queue() : front( 0 ), back ( 0 ) { }~Queue();Type&


16.3.1. Функции-члены шаблонов Queue и QueueItem

Из книги автора

16.3.1. Функции-члены шаблонов Queue и QueueItem Чтобы понять, как определяются и используются функции-члены шаблонов классов, продолжим изучение шаблонов Queue и QueueItem:template class Typeclass Queue {public:Queue() : front( 0 ), back ( 0 ) { }~Queue();Type& remove();void add( const Type & );bool is_empty() const {return front == 0;}private:QueueItem Type


16.5. Статические члены шаблонов класса

Из книги автора

16.5. Статические члены шаблонов класса В шаблоне класса могут быть объявлены статические данные-члены. Каждый конкретизированный экземпляр имеет собственный набор таких членов. Рассмотрим операторы new() и delete() для шаблона QueueItem. В класс QueueItem нужно добавить два


16.6. Вложенные типы шаблонов классов

Из книги автора

16.6. Вложенные типы шаблонов классов Шаблон класса QueueItem применяется только как вспомогательное средство для реализации Queue. Чтобы запретить любое другое использование, в шаблоне QueueItem имеется закрытый конструктор, позволяющий создавать объекты этого класса


16.9. Специализации шаблонов классов A

Из книги автора

16.9. Специализации шаблонов классов A Прежде чем приступать к рассмотрению специализаций шаблонов классов и причин, по которым в них может возникнуть надобность, добавим в шаблон Queue функции-члены min() и max(). Они будут обходить все элементы очереди и искать среди них


16.10. Частичные специализации шаблонов классов A

Из книги автора

16.10. Частичные специализации шаблонов классов A Если у шаблона класса есть несколько параметров, то можно специализировать его только для одного или нескольких аргументов, оставляя другие неспециализированными. Иными словами, допустимо написать шаблон, соответствующий