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

Вопросы для самопроверки

  1. Каково назначение вложенных классов? Какие отношения предметной области они позволяют моделировать?

  2. Каким образом дается внешнее определение вложенного класса? Приведите пример.

  3. Как можно обеспечить доступ вложенного класса к открытым нестатическим данным объемлющего класса?

  4. Приведите практически значимый пример определения класса, который содержал бы вложенный класс, производный от какого-то другого класса. В определение включите только существенные компоненты.

  5. Почему вложенные классы часто приходится делать дружественными к объемлющим классам и наоборот? Ответ поясните примером.

  6. Можно ли вложить иерархию классов в класс? Если да, то как это сделать правильно? Ответ сопроводите примером.

  7. Как выполнить определение и инициализацию статического компонента вложенного класса? Ответ сопроводите примером.

  8. Как правильно определить локальный класс? Перечислите основные правила и приведите пример.

  9. Имеется функция с прототипом в виде void func(int a, double b); В нее вложен класс LocalClass. Каким образом компонентная функция этого класса может получить доступ к аргументам функции func? Приведите фрагмент кода.

  10. Возможно ли наличие статических компонент в локальных классах? Если да, то каких статических компонент и как их правильно определить?

  11. Как определить вложенный класс в локальном классе? Ответ поясните примером.

Задачи

Решить задачи из раздела 3, используя механизм вложенных классов.

5. Объектная модель и шаблоны

Шаблоны являются одним из спорных и наиболее тяжело усваиваемых механизмов языка С++. Однако при четком понимании этого механизма и умелом его применении появляется возможность создавать компактный, гибкий и масштабируемый код.

Чтобы понять сущность шаблонов обратимся к примеру. Пусть нам нужно создать класс, инкапсулирующий работу с матрицами. Предположим вначале, что мы создаем класс для своих «внутренних» потребностей. При этом нам известны возможные типы элементов матрицы (например, это может быть int, unsigned, short, unsigned short, float, double, long double). Написав класс для каждого из перечисленных типов элементов, мы можем решить данную задачу. Однако ясно, что это плохое решение, поскольку мы многократно вынуждены повторять по сути один и тот же код16. А теперь допустим, что мы создаем библиотечный класс, который будет многократно использоваться другими программистами. Понятно, что теперь нам неизвестны возможные типы элементов матрицы, поэтому мы не сможем определить классы «на все случаи».

Для того чтобы устранить этот существенный недостаток, в С++ используется понятие шаблонов. Сразу же отметим, что оно относится не только к классам, но и к функциям, в том числе и компонентным, а также к статическим компонентам классов. Однако далее мы будем рассматривать только шаблоны классов и компонент, поскольку содержание данного пособия связано с объектно-ориентированным программированием.

5.1. Определение, описание и инстанцирование шаблонов

Шаблон классов (или шаблонный класс) определяет неограниченное семейство сходных классов. Определив такой шаблон лишь один раз, мы можем автоматически получать (инстанцировать) различные классы на его основе и формировать объекты этих классов17. Причем формироваться будут только те классы, которые реально нужны в программе.

В общем виде шаблон классов определяется в следующем формате:

template <template_parameter_list> template_class_declaration

где template_parameter_list – список параметров шаблона; template_class_declaration – определение самого шаблонного класса. Список параметров шаблона не может быть пустым и обязательно указывается в угловых скобках, причем отдельные параметры в нем перечисляются через запятые. Определение шаблонного класса выполняется практически так же, как и определение обычного класса.

Важнейшим элементом формата шаблона классов является список параметров шаблона. Он представляет те свойства объединяемых шаблоном классов, которыми эти классы отличаются друг от друга. Например, для шаблона, представляющего матрицы, в список параметров попадет тип элементов матрицы. При инстанцировании шаблона вместо параметров подставляются аргументы, которые конкретизируют обобщенные свойства. Так, в шаблон матриц можно передать аргумент int, выделив тем самым класс матриц с целочисленными элементами. Описание каждого параметра шаблона может начинаться одним из служебных слов class, typename или template, либо именем некоторого типа (стандартного или определенного пользователем). Последующее определение шаблонного класса использует имена из списка параметров шаблона, или, как говорят, является параметризованным. Более подробно о параметрах и аргументах шаблонов мы поговорим позднее, а сейчас рассмотрим несложный пример.

В качестве примера ниже приводится определение шаблонного класса CVector, моделирующего свойства векторов с элементами произвольного типа18.

template <class item_t> class CVector {

item_t * __data; // данные вектора

int __size; // длина вектора

public:

explicit CVector(int); // конструктор

~CVector() { delete[] data; } // деструктор

item_t & Item(int i) { // получение i–го элемента

return data[i];

}

...

};

В примере класс CVector параметризуется типом элементов вектора item_t. Этот обобщенный тип используется для определения массива элементов и возвращаемого значения в функции Item. Это, в свою очередь, дает возможность представления векторов с любым типом элементов.

Шаблон классов можно как определять, так и описывать, т.е. для него существует понятие предварительного объявления. При этом и описание, и определение шаблона могут размещаться только на уровне пространства имен или класса; в блоке или функции локализовать шаблон классов нельзя. Компонентные функции шаблона могут определяться как внутри него (см. деструктор ~CVector и функцию Item), так и за его пределами, т.е. могут иметь внешнее определение (конструктор CVector). Внешнее определение компонент при этом также должно быть параметризовано.

Ниже показано, как в общем виде дается внешнее определение компонентной функции шаблонного класса:

template <template_parameter_list>

value_type template_class_id<template_argument_list>

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