Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP.doc
Скачиваний:
13
Добавлен:
25.04.2019
Размер:
1.34 Mб
Скачать

::Function_id(function_parameter_list) { statements }

Здесь через template_argument_list обозначен список аргументов шаблона (аргументами могут быть, например, имена параметров шаблона); template_class_id<template_argument_list> называют полным идентификатором шаблонного класса19. Оставшаяся часть – это обычное внешнее определение компонентной функции function_id со списком параметров function_parameter_list, использующее параметры шаблона (value_type – тип возвращаемого функцией значения).

Ниже приведено внешнее определение конструктора шаблона CVector, введенного ранее.

template <class item_t> СVector<item_t>::СVector(int n)

{

if (n < 0) throw std::range_error(“invalid size”);

// при отрицательном размере генерируем исключение

// выделение памяти под элементы вектора

__data = new item_t[n];

// обнуление элементов

for (int i = 0; i < n; i++) __data[i] = static_cast<item_t>(0);

// фиксация размера вектора

__size = n;

}

Из заголовка конструктора видно, что он параметризован типом элемента вектора item_t, полное имя конструктора СVector<item_t>::СVector включает идентификатор шаблона СVector<item_t>, собственный параметр конструктора int n задает длину вектора. В теле конструктора используется обобщенный тип item_t.

Кроме компонентных функций, шаблонный класс может содержать статические компоненты. Значения таких компонент будут действовать на уровне отдельных классов, инстанцируемых от шаблона, и могут быть параметризованы. Как и в случае обычных классов, у статических компонент шаблонных классов должно быть внешнее определение. Дается оно в том же пространстве имен, где размещен сам шаблон. А его формат имеет следующий вид:

template <template_parameter_list>

type template_class_id<template_argument_list>

::static_member_id = initializer;

где type – это тип статического компонента (он может каким-то образом зависеть от параметров шаблона); static_member_id – имя статического компонента; initializer – инициализирующее выражение.

Шаблонный класс в качестве компонента может содержать вложенные классы. Их определение и использование незначительно отличается от случая с обычными классами. Так, например, во внешнем определении вложенного в шаблон класса необходимо указание квалифицированного имени класса с полным идентификатором шаблона. Это также касается и внешнего определения компонент вложенного класса.

Ниже дан пример шаблонного класса, включающего статический компонент и вложенный класс:

Пример

// определение шаблонного класса

template <class T> struct X {

static T s;

class Y;

};

// определение статического компонента

template<class T> T X<T>::s = static_cast<T>(0);

// определение вложенного класса

template<class T> class X<T>::Y { /* ... */ };

Когда шаблон определен, от него можно формировать конкретные классы, а затем и объекты этих классов. Получить (инстанцировать) класс из шаблона можно путем указания конкретных аргументов шаблона; сформировать от этого класса объект можно по обычной схеме, принятой для классов, т.е. через вызов одного из конструкторов. Формат вызова конструктора для формирования объекта object_id шаблонного класса template_class_id выглядит так:

template_class_id <template_argument_list> object_id(arguments);

При обработке такого вызова компилятором выполняются два действия. Во-первых, от шаблона template_class_id неявно инстанцируется класс с идентификатором template_class_id<template_argument_list>, т.е. формируется его определение (в этом определении все обобщенные типы заменяются конкретными типами, переданными через аргументы). Во-вторых, формируется код вызова конструктора полученного класса для создания объекта object_id. Например:

CVector <double> Z(10);

В примере инстанцируется класс CVector<double>, от которого порождается объект Z – вектор из десяти вещественных компонент.

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

CVector <double> * pdVector;

Наряду с неявным инстанцированием шаблонных классов возможно их явное инстанцирование. Явное инстанцирование позволяет получить класс от шаблона путем задания конкретных аргументов. Записывается оно в следующем виде:

template <template_parameter_list>

template_class_id<template_argument_list>;

Такую форму инстанцирования разумно применять тогда, когда точно известно, что потребуется класс template_class_id <template_argument_list>.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]