КАТЕГОРИИ: Архитектура-(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; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |