- •Раздел 4. Разработка по Тема 4.1. Проектирование интерфейса с пользователем
- •4.1.1. Типы пользовательских интерфейсов.
- •4.1.2. Пользовательская и программная модели интерфейса.
- •4.1.3. Разработка диалогов.
- •4.1.4. Основные компоненты графических пользовательских интерфейсов.
- •Тема 4.2. Реализация графических пользовательских интерфейсов.
- •4.2.1. Диалоги, управляемые пользователем.
- •4.2.2. Диалоги, управляемые системой.
- •4.2.3. Использование метафор.
- •4.2.4. Технология Drag and Drop.
- •4.2.5. Интеллектуальные элементы.
- •4.3.1. Базовые типы данных.
- •Константы
- •Область действия имен
- •4.3.2. Указатели и адресная арифметика.
- •4.3.3. Составные типы данных. Структуры
- •Битовые поля
- •Определение типов
- •Перечислимые типы
- •4.3.4. Выражения и операции.
- •4.3.5. Управляющие конструкции. Условные операторы
- •Операторы циклов
- •4.4.1. Статические одномерные массивы.
- •4.4.2. Статические многомерные массивы.
- •4.4.3. Динамические массивы.
- •4.4.4. Массивы указателей.
- •4.5.1. Стеки.
- •4.5.2. Очереди.
- •4.5.3. Списки.
- •4.5.4. Бинарные деревья.
- •4.6.1. Объявление классов и экземпляров классов.
- •4.6.2. Инкапсуляция данных и методов.
- •4.6.3. Конструкторы классов.
- •Конструктор по умолчанию
- •Конструктор копирования
- •4.6.4. Деструкторы классов.
- •4.7.1. Разделы в описании класса.
- •4.7.2. Friend-конструкции.
- •4.7.3. Статические члены классов.
- •4.7.4. Использование описателя const в классах.
- •4.8.1. Вложенность классов.
- •4.8.2. Наследование данных и методов.
- •4.8.3. Типы наследования.
- •4.9.1. Полиморфизм раннего связывания.
- •4.9.2. Полиморфизм позднего связывания и виртуальные функции.
- •4.9.3. Абстрактные методы и классы.
- •4.10.1. Функции консольного ввода-вывода.
- •4.10.2. Функции файлового ввода-вывода.
- •4.10.3. Использование библиотеки классов потокового ввода-вывода.
- •4.11.1. Перегрузка операций.
- •4.11.2. Шаблоны функций.
- •4.11.3. Шаблоны классов.
- •4.11.4. Обработка исключений.
- •Тема 4.12. Com-технология.
- •4.12.1. Основные понятия.
- •4.12.2. Типы интерфейсов.
- •Свойства интерфейсов
- •Типы интерфейсов
- •4.12.3. Типы com-объектов.
- •4.12.4. Фабрика классов.
- •Тема 4.13. Построение com-сервера.
- •4.13.1. Язык idl.
- •Содержимое файла idl
- •4.13.2. Определение пользовательского интерфейса.
- •4.13.3. Реализация пользовательского интерфейса.
- •4.13.4. Создание тестового клиента.
- •Тема 4.14. Обзор платформы ms .Net.
- •4.14.1. Общая идея архитектуры .Net.
- •4.14.2. Достоинства и недостатки .Net.
- •4.14.3. Схема трансляции программ в .Net.
- •4.14.4. Язык msil.
- •4.14.5. Объектно-ориентированная модель .Net.
4.11.3. Шаблоны классов.
Шаблон классов (class template) в руководствах программиста иногда называется generic class или class generator – генератор классов. Шаблон действительно помогает компилятору сгенерировать определение конкретного класса по образу и подобию заданной схемы. Разработчики компилятора C++ различают два термина: class template и template class. Первый означает абстрактный шаблон классов, а второй — одно из его конкретных воплощений. Пользователь может сам создать template class для какого-то типа данных. В этом случае созданный класс отменяет (overrides) автоматическую генерацию класса по шаблону для этого типа данных. Рассмотрим стандартный пример, иллюстрирующий использование шаблона для автоматического создания классов, которые реализуют функционирование абстрактного типа данных Вектор линейного пространства. Элементами вектора могут быть объекты различной природы. В примере создаются векторы: целых, вещественных и объектов некоторого класса Circle (вектор окружностей). Для вектора из элементов любого типа тела методов шаблона одинаковы, поэтому и есть смысл объединить их в шаблоне.
template <class T> class Vector // Шаблон классов «Вектор линейного пространства»
{
Т *data ; // Указатель начала массива компонентов
int size; // Размер массива
public:
Vector(int);
~Vector() { deleted data; }
T& operator [](int i) { return data[i]; }
};
// Внешняя реализация тела конструктора
template <class T> Vector<T>:: Vector (int n)
{data = new T[n];}
class Circle // Глобальное определение класса
{
int х. у, r;
public:
Circle () {х=у=r=0;}
Circle (int a, int b, int с) {x=a; y=b; r=c;}
double area () { return 3.14159*r*r; }
};
Vector <int> x(5); // Генерируется вектор целых
int i;
for (i=0; i<5; ++i) x[I]=I;// Инициализация
for (i=0; i<5: ++i) cout«x[i]«' '; // Вывод
Vector <float> y(10); // Генерируется вектор вещественных
for (i=0; i<10: ++i) // Инициализация
y[i] = float(i);
for (i=0; i<10: ++i)
cout«y[i]«' '; //Вывод // Генерируется вектор объектов класса Circle Vector <Circle> z(4); for (i=0: i<4; ++i) //Инициализация
z[i] = Circle(i+100,i+100,i+20); for (i=0; i<4; ++i) //Вывод
cout« z[i].area() « ' ';
}
Обратите внимание на синтаксис внешней реализации тела конструктора шаблона классов. Vector<T> — это имя шаблона. Vector(int n) — имя метода шаблона (конструктор). При использовании шаблона для генерации конкретного вектора объектов необходимо задать в угловых скобках тип данных (известный к этому моменту и видимый в этой области программы). Использование шаблона всегда предполагает наличие описателя типа при имени класса (Vector <type>). Имя Vector теперь не может быть использовано без указания конкретного типа элементов. В рассмотренном примере операция [] определена в шаблоне как общая для всех типов Т, однако метод area() определен только для объектов класса Circle, и он применяется к объекту z[i] класса Circle, вектор из четырех элементов которого автоматически создается компилятором при объявлении Vector <Circle> z(4);.
Если для какого-то типа переменных автоматически сгенерированный по шаблону класс не подходит, то его следует описать явно. Созданный таким образом класс (template class) отменяет автоматическое создание класса по шаблону только для этого типа. Например, пусть для вновь созданного типа:
typedef int (*Tfunc)(int);
(указатель на функцию, возвращающую значение типа int и требующую аргумент типа int) мы не хотим использовать class template Vector, но хотим создать вектор указателей на функции, работающий иначе. С этой целью мы явно описываем конкретное воплощение (template class) класса Vector для типа Tfunc:
class Vector <Tfunc>
{
Tfunc *data;
int size;
public:
Vector (int, Tfunc);
-Vector () { delete [] data; }
Tfunc& operator [] (int i) { return data[i]; }
Vector <Tfunc> :: Vector (int n, Tfunc f)
{
size = n;
data = new Tfunc[n];
for (int i=0: i<n; i++)
data[i]=f;
}
Здесь отличие от шаблона состоит в том, что конструктор класса Vector <Tfunc> имеет теперь два параметра, а не один, как было в шаблоне. Кроме этого, весь вектор указателей на функции инициализируется адресом одной и той же функции, поданной на вход конструктора. Для проверки функционирования вектора из элементов типа Tfunc следует создать какую-нибудь тестовую функцию нужного типа, а в функцию main добавить манипуляции с реальным вектором типа Tfunc. Например:
int func (int j)
{
int i=j*2;
cout<<”\n func:”<< j<<”=”<<i;
return i ;
}
Vector <Tfunc> ff (5, func);
for (i=0; i<5; ++i)
cout « ff[i](i) « ' ' ;
Обратите внимание на то, что при создании вектора ff (5, func); из пяти указателей на функции вторым параметром передается имя функции, а следовательно, ее адрес, инициализирующий все элементы массива f f типа Vector <Tfunc>.