Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

A 1b 2 с 3d 4e




Классы и шаблоны

Локальные классы

Класс может быть определен внутри блока, например внутри тела функции. Такой класс называется локальным. Локализация класса пред­полагает недоступность его компонентов вне области определения класса (вне тела функции или блока, в котором он описан или определен).

Локальный класс не может иметь статических данных, так как компо­ненты локального класса не могут быть определены вне текста класса.

Внутри локального класса разрешено использовать из объемлющей его области только имена типов, статические (static) переменные, внеш­ние (extern) переменные, внешние функции и элементы перечислений. Из того, что запрещено, важно отметить переменные автоматической памяти. Существует еще одно важное ограничение для локальных классов - их компонентные функции могут быть только встроенными (inline).

Для иллюстрации особенностей, локальных классов рассмотрим сле­дующую задачу. Пусть требуется определить класс "квадрат". Ограничим­ся квадратами, стороны которых параллельны осям прямоугольной декартовой системы координат. Исходными данными для задания каждого конкретного квадрата (объекта класса "квадрат") будут координаты центра и размер стороны. Внутри класса "квадрат" определим локальный класс "отрезок". Исходными данными для определения каждого конкретного отрезка будут координаты его концов. Четыре отрезка с соответствующим образом выбранными концевыми точками составят квадрат. Именно та­ким образом можно будет изобразить квадрат на экране (как изображения четырех отрезков).

//Р10-10.СРР - внешние, локальные и глобальные классы

#include <conio.h>

#include "point.cpp" // Внешний класс "точка"

class square // Глобальный класс "квадрат"

{ class segment // Локальный класс "отрезок"

{ point pn, pk; // Точки начала и конца отрезка

public: // Конструктор отрезка

segment(point pin = point(0,0), point pik = point(0,0))

{ pn.givex() - pin.givex(); pn.givey() = pin.givey();

pk.givex() = pik.givex(); pk.givey() = pik.givey(); }

// Доступ к граничным точкам отрезка:

point& beg(void) { return pn; } point& end(void) { return pk; }

void showSeg() // Изобразить отрезок на экране

{ line (pn.givexO, pn.givey(),

pk.givexO, pk.givey(); } }; // Конец определения класса segment

segment ab, be, cd, da; // Отрезки - стороны квадрата public:

// Конструктор квадрата:

square (point ci = point(0,0), int di = 0)

{ // Вершины квадрата - локальные объекты

// конструктора:

point а, b, с, d; a.givex() = ci.givex() - di/2; a.givey() = ci.givey() - di/2; b.givex() = ci.givex() + di/2;

b. giveyz() = ci.givey() - di/2; c.givex() = ci.givex() + di/2;

c. givey() = ci.givey() + di/2; d.givex() + ci.givex() - di/2; d.givey () = ci.giveyO + di/2;

// Граничные точки отрезков:

ab.beg() = a; ab.end() = b; bc.beg() = b; bc.end() = c; cd.beg() = c; cd.end() = d; da.beg() = d; da.end() = a;

}

void showSquare(void) // изобразить квадрат

{ ab.showSeg();

be.showSeg();

cd.showSeg ();

da.showSeg(); } }; // Конец определения класса "квадрат"

void main ()

{ // Переменные для инициализации трафики:

int dr = DETECT, mod;

// Инициализация графической системы:

initgraph(fidr,fimod,"с:\\borlandc\\bgi");

point pi(80,120);

point p2(250,240);

square A{pl,30);

square B(p2,140);

A.showSquare(); getch();

В.showSquare (); getch();

closegraph(); }

Результат в графическом виде показан на рис. 10.9.

Рис.10.9. Изображения на экране при выполнении программы Р10-10. СРР

Отметим некоторые особенности программы. Класс "квадрат" (square) включает в качестве данных четыре стороны - отрезки аb, bc, cd, da, каждый из которых есть объект локального класса segment. Конструктор класса square <) по заданным центру квадрата и размеру стороны определяет значения точек-вершин, а уже по ним формирует отрезки - стороны квадрата.

Шаблоны, которые иногда называют родовыми или параметризо­ванными типами, позволяют создавать (конструировать) семейства родственных функций и классов [2], [9].

Как уже говорилось в главе 6, шаблон семейства функций {function template) определяет потенциально неограниченное множество род­ственных функций. Он имеет следующий вид:

template <список_параметров_шаблона> определекие_функции

Здесь угловые скобки являются неотъемлемым элементом опреде­ления. Список параметров шаблона должен быть заключен именно в угловые скобки.

Аналогично определяется шаблон семейства классов:

template <список_параметров_шаблона> определение класса

Шаблон семейства классов определяет способ построения отдель­ных классов подобно тому, как класс определяет правила построения и формат отдельных объектов. В определении класса, входящего в шаблон, особую роль играет имя класса. Оно является не именем от­дельного класса, а параметризованным именем семейства классов.

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

Следуя авторам языка и компилятора Си++ [2, 9], рассмотрим векторный класс (в число данных входит одномерный массив). Какой бы тип ни имели элементы массива (целый, вещественный, с двойной точностью и т.д.), в этом классе должны быть определены одни и те же базовые операции, например доступ к элементу по индексу и т.д. Если тип элементов вектора задавать как параметр шаблона класса, то система будет формировать вектор нужного типа (и соответствую­щий класс) при каждом определении конкретного объекта.

Следующий шаблон позволяет автоматически формировать клас­сы векторов с указанными свойствами:

//TEMPLATE.VEC - шаблон векторов template

<class T> // Т - параметр шаблона class Vector

{ Т *data; // Начало одномерного массива

int size; // Количество элементов в массиве

public:

Vector(int); // Конструктор класса vector

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

// Расширение действия (перегрузка) операции "[]":

Т& operator[] (int i) { return data[i]; } };

// Внешнее определение конструктора класса:

template <Cclass T> Vector <T>::Vector(int n) { data = new T[n];

size = n; };

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

имя_параиетризованного_класса

<фактические_параметры_шаблона> имя_объекта (паракетры_конструктора);

В нашем случае определить вектор, имеющий восемь веществен­ных координат типа double, можно следующим образом:

Vector <double> Z(8); Проиллюстрируем сказанное следующей программой:

//Р10-11.СРР - формирование классов с помоцью шаблона

#include "template.vec" // Шаблон классов "вектор"

#include <iostream.h>

main()

{ // Создаем объект класса "целочисленный вектор":

Vector <int> Х(5);

// Создаем объект класса "символьный вектор":

Vector <char> C(5);

// Определяем компоненты векторов:

for (int i = 0; i < 5; i++)

{ X[i] = i; C[i] = 'A' + i;}

for (i - 0; i < 5; i++)

cout << " " << X[i] << ' ' << C[i]; }

Результат выполнения программы:

В программе шаблон семейства классов с общим именем vector используется для формирования двух классов с массивами целого и символьного типов. В соответствии с требованием синтаксиса имя параметризованного класса, определенное в шаблоне (в примере Vector), используется в программе только с последующим конкрет­ным фактическим параметром (аргументом), заключенным в угловые скобки. Параметром может быть имя стандартного или определенно­го пользователем типа. В данном примере использованы стандартные типы int и char. Использовать имя Vector без указания фактического параметра шаблона нельзя - никакое умалчиваемое значение при этом не предусматривается.

В списке параметров шаблона могут присутствовать формальные параметры, не определяющие тип, точнее - это параметры, для кото­рых тип фиксирован:

//Р10-12.СРР #include <iostream.h> template <class T, int size = 64> class row { T *data; int length; public: row()

{ length = size;

data = new T[size];

}

~row() { deleted data; } T& operator [] (int i) { return data[i]; }

};

void main О { row <float,8> rf; row <int,8> ri; for (int i = 0; i < 8; i++)

{ rf[i] = i; ri[i] = i * i; } for (i = 0; i < 8; i++)

cout<<«" " << rf[i] << ' ' << ri[i]; }

Результат выполнения программы:




Поделиться с друзьями:


Дата добавления: 2014-01-11; Просмотров: 360; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.007 сек.