Цель работы: Получение навыка работы с иерархическими структурами.
Домашнее задание
1.1. Тщательно изучите листинг программ №1. Нарисуйте блок-схему функции iTakeOut.
1.2. Составьте произвольный список из учеников вашей группы с вашей фамилией в начале списка. Нарисуйте дерево, использую составленный список.
Лабораторное задание
2.1. Наберите программу №1 (комментарии можно не набирать).
#include "stdafx.h"
#include <stdlib.h>
# include <string.h>
# include <stdio.h>
# include <malloc.h>
# include <conio.h>
# define STAFF struct sStaffType
STAFF // Учебно-вспомогательный персонал
{
int iYearsOfService; // Время работы (лет)
float fHourlyWage; // Почасовая оплата
};
# define STUDENT struct sStudentType
STUDENT
{
float fGradePtAverage; // Средний рейтинг
int iLevel; // Год обучения
};
# define PROFESSOR struct sProfType
PROFESSOR
{
int iDepartmentNumber; // Номер кафедры
float fAnnualSalary; // Годовая зарплата
};
# define NODE_TYPE enum eNodeType
typedef NODE_TYPE {student, professor, staff};
# define TREE struct sTree
TREE
{
char sLastName[15]; // Фамилия
char sFirstName[15]; // Имя
int iAge; // Возраст
TREE *Left, *Right; // Указатели на левый и правый листья (ветви)
NODE_TYPE tag; // описатель типа узла - студент или профессор или УВП
union
{
STUDENT student;
PROFESSOR professor;
STAFF staff;
} uNodeTag; // Обьединение, содержащее информацию по
}; // студенту или сотруднику университета
extern void Insert(TREE **root, TREE *item); // Вставить в дерево новый элемент item
extern void Display(TREE *root); // Показать содержимое дерева
extern int iIsPresent(TREE *root, TREE *item); // Содержится ли информация item в дереве?
extern int iTakeOut(TREE **root, TREE *item); // Удалить элемент item из дерева
extern void Destroy(TREE *root); // Уничтожить дерево
static TREE* CreateNode(TREE* item) // Создать элемент item
{
TREE* node;
node = (TREE*) malloc(sizeof(TREE));
*node = *item;
return node;
}
void Destroy(TREE* root) // Уничтожить дерево
{
if (root) // Обратите особое внимание на рекурсивную работу этой функции
{
Destroy(root->Left);
Destroy(root->Right);
free(root); // Освободить память, которая была выделена для узла дерева
}
root = 0;
}
int iTakeOut(TREE** root, TREE* item) // Удалить элемент item из дерева
{
TREE *previous = 0, // Предыдущий узел дерева
*present = *root, // Текущий узел дерева
*replace, // Вспомогательные узлы,
*s, // используемые для перемещения элементов
*parent; // дерева после удаления найденного узла
int iFound = 0;
while (present &&!iFound) // Пока не будет найден элемент item
{
if(strcmp(item->sLastName, present->sLastName) == 0)
iFound = 1; // Информация по человеку с таким именем и фамилией есть в дереве
else
{
previous = present;
// Если ASCII представление фамилии из item меньше ASCII кода фамилии
// из текущего узла дерева (present), то перейти к просмотру левого
// узла (листа) относительно present, иначе - правого
if(strcmp(item->sLastName, present->sLastName) < 0)
present = present->Left;
else
present = present->Right;
}
}
if (iFound) // если item присутствует в дереве
{
if (present->Left == 0) // Если найденный элемент не имеет ветви слева
replace = present->Right;
else
{
if (present->Right == 0) // Если найденный элемент не имеет ветви справа
replace = present->Left;
else // Если удаляемый элемент имеет и левую и правую ветвь (листья)
{
parent = present;
replace = present->Right;
s = replace->Left;
// Теперь необходимо подвинуть все элементы ветви, чтобы избежать разрыва
// дерева при удалении найденного элемента (present)
while (s!= 0) // Пока не будет достигнут крайний левый лист в рассматриваемой ветви
{ // Спускаемся вниз дерева по левой ветви
parent = replace;
replace = s;
s = replace->Left;
}
if (parent!= present) // Есть левая ветвь от правой ветви от найденного элемента
{
parent->Left = replace->Right; // Правую подветвь переносимого элемента сделать левой подветвью предыдущего
replace->Right = present->Right; // Переместить элемент на место удаляемого
}
replace->Left = present->Left; // Переместить левую ветвь
}
}
if (previous == 0) // Элемент лежит сразу же за корнем дерева
*root = replace;
else
if(present == previous->Left) // Предыдущий спуск был по левой ветви
previous->Left = replace;
else // Предыдущий спуск был по правой ветви
previous->Right = replace;
free (present); // Удалить найденный элемент
}
return iFound; // 1 - если элемент был удален, 0 - если такого элемента в дереве не было
}
void Insert(TREE **root, TREE *item) // Вставить элемент item в дерево
{
TREE *parent = 0,
// current (текущий) указатель на дерево указывает на его вершину (корень)
*current = *root;
TREE *new_node; // Новый узел
int iFound = 0;
while (current &&!iFound) // Пока элемент item не найден
{
if (strcmp(item->sLastName, current->sLastName) == 0) iFound = 1;
else
{
parent = current;
if (strcmp(item->sLastName, current->sLastName) < 0)
current = current->Left; // перемещаться по левой ветви
else
current = current->Right; // перемещаться по правой ветви
}
}
if (iFound == 0)
{
if (parent == 0) // в дереве нет еще элементов - создаем его
{
*root = CreateNode(item); // создать узел
(*root)->Left = (*root)->Right = 0;
}
else // Вставить узел в дерево
{
new_node = CreateNode(item);
new_node->Left = new_node->Right = 0;
if (strcmp(item->sLastName, parent->sLastName) < 0)
parent->Left = new_node;
else
parent->Right = new_node;
}
}
}
void Display(TREE *root) // Показать дерево
{
if(root) // Обратите внимание также на рекурсивный обход дерева
{
Display(root->Left);// показать вначале левую ветвь (лист) дерева
printf("\n%s, %s", root->sLastName, root->sFirstName);
printf("\n Old - %d", root->iAge);
switch(root->tag) // Обратите внимание на использование в
{ // конструкции switch элементов перечислимого
case student: // (enum) типа
printf("\nReyting: %.2f",
root->uNodeTag.student.fGradePtAverage);
printf("\nKurs: %d\n", root->uNodeTag.student.iLevel);
break;
case professor:
printf("\nNumber of kafedra: %d",
root->uNodeTag.professor.iDepartmentNumber);
printf("\nYear selary: %.2f\n",
root->uNodeTag.professor.fAnnualSalary);
break;
case staff:
printf("\n Time of work(year): %d",
root->uNodeTag.staff.iYearsOfService);
printf("\nSelary of oure: %.2f\n",
root->uNodeTag.staff.fHourlyWage);
}
Display(root->Right); // Вывести информацию о содержимом правого узла
}
}
int iIsPresent(TREE *root, TREE *item)
{
TREE *current = root; // Устанавливаем указатель на вершину (корень) дерева
int iFound = 0;
while (current &&!iFound) // пока элемент item не найден
{
if (strcmp(item->sLastName, current->sLastName) == 0) iFound = 1;
else
{ // Если ASCII код фамилии из item меньше ASCII кода из текущего узла (current)
if (strcmp(item->sLastName, current->sLastName) < 0)
current = current->Left; // то перейти к рассмотрению левого узла
else
current = current->Right; // иначе перейти к рассмотрению правого узла
}
}
return iFound; // Если не найден - 0, если найден - 1
}
TREE* sMyTree;
void main()
{
// Выделяем память на три узла дерева
TREE* item1 = (TREE*) malloc(sizeof(TREE));
TREE* item2 = (TREE*) malloc(sizeof(TREE));
TREE* item3 = (TREE*) malloc(sizeof(TREE));
// Инициализация первого элемента
strcpy(item1->sLastName, "Fyfikov");
strcpy(item1->sFirstName, "Ziberman");
item1->iAge = 32;
item1->tag = staff;
item1->uNodeTag.staff.iYearsOfService = 3;
item1->uNodeTag.staff.fHourlyWage = 5.25;
// Вставить элемент в дерево
Insert(&sMyTree, item1);
strcpy(item2->sLastName, "Vibigalo");
strcpy(item2->sFirstName, "Ivanov");
item2->iAge = 56;
item2->tag = professor;
item2->uNodeTag.professor.iDepartmentNumber = 7;
item2->uNodeTag.professor.fAnnualSalary = 15321.0;
Insert(&sMyTree, item2);
strcpy(item3->sLastName, "Sidorov");
strcpy(item3->sFirstName, "Antonov");
item3->iAge = 18;
item3->tag = student;
item3->uNodeTag.student.iLevel = 1;
item3->uNodeTag.student.fGradePtAverage = 0.75;
Insert(&sMyTree, item3);
Display(sMyTree); // Показать дерево
getchar();
if(iIsPresent(sMyTree, item2))
printf("\n 2- element out of tree\n");
else
printf("\n element out of tree\n");
getchar();
iTakeOut(&sMyTree, item1);
Display(sMyTree);
getchar();
iTakeOut(&sMyTree, item2);
Display(sMyTree);
getchar();
iTakeOut(&sMyTree, item3);
Display(sMyTree);
getchar();
printf("\n");
}
2.3. Запустите программу и проанализируйте результаты ее работы.
2.4. Измените программу таким образом, чтобы в дерево можно было бы вставлять информацию о студентах колледжа.
2.5 Измените программу так, чтобы в дерево можно было вставлять однофамильцев.
2.6 Модифицируйте класс sTree так, чтобы его объекты можно было вставлять в контейнер set библиотеки STL. Продемонстрируйте примеры вставки.
Содержание отчета
- Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.
- Выполненное домашнее задание.
- Тексты программ, написанных при выполнении 2.4, 2.5 и 2.6 пунктов лабораторного задания.
Вопросы к защите
3.1. Использую библиотеку STL, напишите класс вектор целых чисел.
3.2. Использую библиотеку STL, напишите класс очередь вещественных чисел.
3.3. Использую библиотеку STL, напишите класс список символьных переменных.
3.4. Использую библиотеку STL, напишите класс множество символьных переменных.
3.5. Использую библиотеку STL, напишите класс мультимножество символьных переменных.
3.6. Нарисуйте пример двоичного дерева поиска и покажите, как изменяется его структура при удалении из него элемента.
3.7. Нарисуйте пример двоичного дерева поиска и покажите, как изменяется его структура при вставке в него элемента.
3.8. Напишите функцию сохранения и восстановления дерева из файла.
3.9. Напишите функцию, позволяющую найти и отредактировать содержимое любого узла в дереве.
3.10. Напишите функцию, выводящую на экран информацию о узлах дерева удовлетворяющих заданному с клавиатуры пользователем диапазону (например, вывести все узлы начинающиеся с букв от В до Е).
3.11. Модифицируйте программу так, чтобы фамилия и имя в узле дерева заносились не в статический, а динамический массив памяти.
Лабораторная работа N 10
Наследование классов в языке С++
Цель работы: Получение навыка работы с наследованием классов в языке С++
Домашнее задание
1.1. Тщательно изучите листинг программ №1. Постройте графы иерархии классов.
1.2 Письменно поясните термины инкапсуляция и интерфейс, наследование интерфейса и наследование реализации, композиция и агрегация в языке С++. С помощью каких средств языка они реализованы.
Лабораторное задание
2.1. Наберите программу №1.
// Figura.cpp:
#include "stdafx.h"
#include "afxwin.h"
#include "iostream"
using namespace std;
class Figure{
static HWND hwnd;
protected:
static HDC hdc;
public:
Figure(){/*cout<<"\n Figure()";*/}
void show(){}
void hide(){}
void move(int x, int y){}
static void InitGraphic(){hwnd=FindWindow(_T("ConsoleWindowClass"),_T("C:\\Windows\\system32\\cmd.exe"));hdc=GetWindowDC(hwnd);}
static void CloseGraphic(){ReleaseDC(hwnd, hdc); CloseHandle(hwnd);}
~Figure(){/*cout<<"\t ~Figure()";*/}
};
HWND Figure::hwnd = 0;
HDC Figure::hdc = 0;
class Square: public Figure {
POINT pt[5];
public:
Square(POINT* p){
for(int i =0; i <5; i++){pt[i].x = p[i].x;pt[i].y = p[i].y;}
}
void show(){
CPen pen(PS_SOLID,2,RGB(255,0,0));
SelectObject(hdc,pen);
Polyline(hdc,pt,5);
}
void hide(){
CPen pen(PS_SOLID,2,RGB(0,0,0));
SelectObject(hdc,pen);
Polyline(hdc,pt,5);
}
void move(int x, int y){for(int i = 0; i<5;i++){ pt[i].x+=x;pt[i].y+=y;} }
~Square(){/*cout<<"\t ~Square()";*/}
};
class ClsEllipse: public Figure {
public:
CPoint pt1,pt2;
ClsEllipse(){/*cout<<"\t ClsEllipse()";*/
pt1.x=100; pt1.y=100;
pt2.x=200; pt2.y=200;
}
void show(){
CPen pen(PS_SOLID,2,RGB(0,255,0));
SelectObject(hdc,pen);
Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);
}
void hide(){
CPen pen(PS_SOLID,2,RGB(0,0,0));
SelectObject(hdc,pen);
Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);
}
void move(int x, int y){ pt1.x+=x,pt1.y+=y,pt2.x+=x,pt2.y+=y; }
~ClsEllipse(){/*cout<<"\t ~ClsEllipse()";*/}
};
//Включение объектов
class MyObject{
Square sq1, sq2; //Композиция (агрегирование по значению)
ClsEllipse& elp; //Агрегация (агрегирование по ссылке)
public:
MyObject(const Square& p1,const Square& p2,ClsEllipse& el):sq1(p1),sq2(p2), elp(el){/*cout<<"\t MyObject()";*/}
void show(){sq1.show(); sq2.show();elp.show();}
void move(int x, int y){sq1.move(x,y); sq2.move(x,y);elp.move(x,y);}
void hide(){sq1.hide(); sq2.hide(); elp.hide();}
~MyObject(){/*cout<<"\n ~MyObject()";*/}
};
//Множественное наследование
class Heir: Square, ClsEllipse{
public:
Heir(POINT *p):Square(p),ClsEllipse(){/*cout<<"\t Heir()";*/ }
void show(){Square::show(); ClsEllipse::show();}
void move(int x, int y){Square::move(x,y); ClsEllipse::move(x,y);}
void hide(){Square::hide(); ClsEllipse::hide();}
~Heir(){/*cout<<"\n ~Heir()";*/}
};
void ShowMyObject(MyObject obj){
for(int i = 0; i <100; i++){obj.show(); Sleep(24); obj.hide(); obj.move(4,0);}
}
void main(){
POINT pt1[5];
pt1[0].x = 40;pt1[0].y=40;
pt1[1].x = 40;pt1[1].y=140;
pt1[2].x = 140;pt1[2].y=140;
pt1[3].x = 140;pt1[3].y=40;
pt1[4].x = 40;pt1[4].y=40;
Figure::InitGraphic();
{
Square sq1(pt1); ClsEllipse elp;
for(int i = 0; i <100; i++){ sq1.show();elp.show(); Sleep(24); sq1.hide(); elp.hide(); sq1.move(1,1); elp.move(2,2);}
}
ClsEllipse elp;
Square sq2(pt1);
sq2.move(20,20);
MyObject obj(pt1, sq2, elp);
getchar();
ShowMyObject(obj);
{
Heir hr(pt1);
getchar();
for(int i = 0; i <100; i++){hr.show(); Sleep(24); hr.hide(); hr.move(0,3);}
}
Figure::CloseGraphic();
}
2.2. Определите классы линия, треугольник, трапеция.
2.3. Получите у преподавателя рисунок и, используя разработанные классы, нарисуйте его на экране, применив множественное наследование и включение.
2.4 Переопределить один из классов с помощью указателей.
Содержание отчета
3.1 Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.
3.2 Выполненное домашнее задание.
3.3 Тексты программ, написанные при выполнении 2.2, 2.3 и 2.4 пунктов лабораторного задания.
Вопросы к защите
4.1. Расскажите о методах декомпозиции системы.
4.2. Приведите примеры иерархичных систем.
4.3. Расскажите о переопределении данных и методов базового класса в производном классе.
4.4. Раскройте понятия инкапсуляция и интерфейс класса. С помощью каких средств языка они реализованы.
4.5. Реализуйте класс Square, используя динамическую память.
4.6. Реализуйте класс ClsEllipse, используя динамическую память.
4.7. Реализуйте класс MyObject, используя динамическую память.
4.8. Напишите классы абитуриент и производный от него студент. Поясните механизм наследования.
4.9. Напишите классы университет и факультет и на их примере поясните, что такое композиция.
4.10. Напишите классы преподаватель и факультет и на их примере поясните, что такое агрегация.
Лабораторная работа N 11
Абстрактные классы и виртуальные функции С++
Цель работы: Получение навыка работы с виртуальными функциями и абстрактными классами в языке С++
Домашнее задание
1.1. Тщательно изучите листинг программ №1. Постройте граф иерархии классов.
1.2 Поясните письменно термины: инкапсуляция, интерфейс, наследование, полиморфизм, агрегирование, делегирование в отношении классов языка С++. С помощью каких средств языка они реализованы.
Лабораторное задание
2.1. Наберите программу №1.
// В свойствах проекта в опциях по C/С++ ->Библиотека времени выполнения; установить /MTd
//В свойствах проекта Компоновщик->Ввод->Дополнительные зависимости; поставьте на первое место uafxcwd.lib
#include "stdafx.h"
#include "afxwin.h"
#include "iostream"
using namespace std;
HWND hwnd = 0;
HDC hdc = 0;
void InitGraphic(){
system("mode con cols=168 lines=55"); system("pause >> void");
hwnd=FindWindow(_T("ConsoleWindowClass"),_T("C:\\Windows\\system32\\cmd.exe"));hdc=GetWindowDC(hwnd);
}
void CloseGraphic(){ReleaseDC(hwnd, hdc); CloseHandle(hwnd);}
//-------------------------------------------------------------------------- IFigure
class IFigure{ //интерфейсный класс
protected:
int fMove; //0 - фигура двигается; 1 - фигура мигает на месте; 2 - фигура стоит на месте;
int fClr; //0 - фигура цвет не меняет; 1 - фигура меняет цвет
public:
IFigure(): fMove(0), fClr(0){/*cout<<"\n IFigure()";*/}
virtual void show()=0;
virtual void hide()=0;
virtual void move(int x, int y)=0;
};
//-------------------------------------------------------------------------Square
class Square:virtual public IFigure {
POINT pt[5];
COLORREF color;
public:
Square(POINT* p): color(RGB(255,0,0)){ for(int i =0; i <5; i++) pt[i] = p[i]; }
void SetColor(COLORREF cl){color = cl;}
void show(){
CPen pen(PS_SOLID,2,color);
SelectObject(hdc,pen);
Polyline(hdc,pt,5);
}
void hide(){
CPen pen;
pen.CreatePen(PS_SOLID,2,RGB(0,0,0));
SelectObject(hdc,pen);
Polyline(hdc,pt,5);
}
void move(int x, int y){for(int i = 0; i<5;i++){ pt[i].x+=x;pt[i].y+=y;} }
virtual ~Square(){/*cout<<"\t ~Square()";*/}
};
//---------------------------------------------------------------------------ClsEllipse
class ClsEllipse: virtual public IFigure {
CPoint pt1,pt2;
public:
ClsEllipse():pt1(100,100),pt2(200,200) {}
virtual void show() {
CPen pen(PS_SOLID,2,RGB(0,255,0));
SelectObject(hdc,pen);
Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);
}
virtual void hide() {
CPen pen(PS_SOLID,2,RGB(0,0,0));
SelectObject(hdc,pen);
Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);
}
virtual void move(int x, int y) { pt1.x+=x,pt1.y+=y,pt2.x+=x,pt2.y+=y; }
virtual ~ClsEllipse(){/*cout<<"\t ~ClsEllipse()";*/}
};
//-------------------------------------------------------------------------Rectan
class Rectan: public IFigure {
Square* pSq;
public:
//дописать operator=
virtual void show(){pSq->show();}//Делегирование
virtual void move(int x, int y){pSq->move(x,y);}//Делегирование
virtual void hide(){pSq->hide();}//Делегирование
void SetColor(COLORREF cl){pSq->SetColor(cl);}
Rectan (Square& p){pSq = new Square(p);}
virtual ~Rectan(){delete pSq;}
};
//-------------------------------------------------------------------------DrowTxt
class DrowTxt{
CString str;
public:
DrowTxt(CString s):str(s){}
void show(){
CDC* pCDC = CDC::FromHandle(hdc);
pCDC->SetTextColor(RGB(255,0,0));
pCDC->SetBkColor(RGB(0,0,0));
pCDC->TextOutW(300,100,str); pCDC->TextOutW(0,0," ");
}
};
//-------------------------------------------------------------------------Heir
class Heir: public Square, public ClsEllipse{ //Виртуальный базовый класс
public: //(Множественное наследование)
Heir(POINT *p):Square(p),ClsEllipse(){/*cout<<"\t Heir()";*/ }
void show(){Square::show(); ClsEllipse::show();}
void move(int x, int y){Square::move(x,y); ClsEllipse::move(x,y);}
void hide(){Square::hide(); ClsEllipse::hide();}
virtual ~Heir(){/*cout<<"\n ~Heir()";*/}
};
//------------------------------------------------------------------------RecordPlayer
class RecordPlayer{ //Чтобы воспользоваться классом, объекты должны поддерживать интерфейс IFigure
IFigure**pFig;//Массив указателей IFigure*
int n; //Текущее количество указателей в массиве
int N; //Размерность массива
public:
void Insert(IFigure* pF){if (n<N) pFig[n++] =pF; }
RecordPlayer(int Nfig): N(Nfig), n(0) { pFig = new IFigure*[N]; }
virtual void show(){ for(int i = 0; i < n; i++) pFig[i]->show(); }//Полиморфизм
virtual void hide(){ for(int i = 0; i < n; i++) pFig[i]->hide(); }//Полиморфизм
virtual void move(int x, int y){ for(int i = 0; i < n; i++) pFig[i]->move(x,y); }//Полиморфизм
void PlayMyObject(int x, int y){ for(int i = 0; i <150; i++){show();Sleep(24);hide(); move(x,y);} show();}
virtual ~RecordPlayer(){delete []pFig;}
};
void main(){
POINT pt1[5];
pt1[0].x = 40;pt1[0].y=40;
pt1[1].x = 40;pt1[1].y=140;
pt1[2].x = 140;pt1[2].y=140;
pt1[3].x = 140;pt1[3].y=40;
pt1[4].x = 40;pt1[4].y=40;
InitGraphic();
DrowTxt dtxt("Привет");
dtxt.show();
getchar();
Heir hr(pt1);
for(int i = 0; i <100; i++){hr.show(); Sleep(24); hr.hide(); hr.move(0,3);}
getchar();
ClsEllipse elp;
Square sq1(pt1), sq2(pt1), sq3(pt1);
sq1.SetColor(RGB(255,255,0)); sq2.SetColor(RGB(0,255,0));
sq3.SetColor(RGB(0,0,255)); hr.SetColor(RGB(0,255,255));
sq2.move(20,20); sq3.move(40,30); hr.move(0,-150);
Rectan rec(sq3);
RecordPlayer RPlayer(5);
RPlayer.Insert(&elp);
RPlayer.Insert(&sq1);
RPlayer.Insert(&sq2);
RPlayer.Insert(&rec);
RPlayer.Insert(&hr);
RPlayer.PlayMyObject(3,0);
getchar();
CloseGraphic();
}
2.2 Доопределите класс Rectan.
2.3 Модифицируйте класс ClsEllipse так, чтобы параметры эллипса можно было задавать через конструктор, и объекты этого класса могли менять свой цвет.
2.4 Модифицируйте класс DrowTxt так, чтобы он мог быть использован классом RecordPlayer для воспроизведения на экране.
2.5 Напишите класс «текст в прямоугольнике» так, чтобы он мог быть использован классом RecordPlayer для воспроизведения на экране.
2.6 Модифицируйте программу так, чтобы объекты на экране с помощью класса RecordPlayer могли двигаться, оставаться неподвижными, мигать, изменять свой цвет.
2.7 Получите рисунок у преподавателя и напишите программу, рисующую его на экране с помощью класса RecordPlayer.
Содержание отчета
3.1 Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.
3.2 Выполненное домашнее задание.
3.3 Тексты классов, написанных при выполнении 2.2 – 2.7 пунктов лабораторного задания.
Вопросы к защите
4.1. Расскажите о виртуальных функциях и полиморфизме.
4.2. Что такое абстрактные классы, для чего они нужны?
4.3. Расскажите о переопределении данных и методов базового класса в производном классе.
4.4. Раскройте понятия инкапсуляция и интерфейс класса. С помощью каких средств языка они реализованы.
4.5. Реализуйте класс круг, вписанный в квадрат, и выведите его на экран с помощью класса RecordPlayer.
4.6. Реализуйте класс ClsEllipse, используя динамическую память.
4.7. Реализуйте класс Square, используя динамическую память.
4.8. Напишите класс «магазин», который работает с объектами абстрактного класса «товар». Определите 2-3 класса, производных от класса «товар». Продемонстрируйте примеры полиморфного поведения.
4.9. Напишите класс «вагон», который работает с объектами абстрактного класса «груз». Определите 2-3 класса, производных от класса «груз». Продемонстрируйте примеры полиморфного поведения.
Лабораторная работа N 12
Библиотека STL
Цель работы: Получение навыка работы с библиотекой STL
Домашнее задание
1.1. Тщательно изучите листинг программ №1. Опишите, что делает класс CountedPtr.
1.2 Письменно в отчёте приведите все компонентные функции одной из коллекций из библиотеки STL.
Лабораторное задание
2.1. Наберите программу №1.
#include "stdafx.h"
#include <iostream>
#include <list>
#include <deque>
# include <set>
#include <algorithm>
using namespace std;
/* Класс, обеспечивающий семантику подсчёта ссылок.
* Объект, на который ссылается указатель, автоматически
* уничтожается при удалении последнего экземпляра CountedPtr
* для данного объекта.
*/
template <class T>
class CountedPtr {
private:
T* ptr; // Указатель на значение
long* count; // Количество владельцев (общие данные)
public:
// Инициализация объекта существующим указателем
// - указатель p должен быть получен в результате вызова new
explicit CountedPtr(T* p = 0)
: ptr(p), count(new long(1)) {
}
// Копирующий указатель (увеличивает счётчик владельцев)
CountedPtr(const CountedPtr<T>& p) throw()
: ptr(p.ptr), count(p.count) {
++*count;
}
// Деструктор (уничтожает объект, если владелец был последним)
~CountedPtr() throw() {
dispose();
}
// Присваивание (перевод указателя на новый объект)
CountedPtr<T>& operator= (const CountedPtr<T>& p) throw() {
if (this!= &p) {
dispose();
ptr = p.ptr;
count = p.count;
++*count;
}
return *this;
}
// Доступ к объекту, на который ссылается указатель
T& operator*() const throw() {
return *ptr;
}
T* operator->() const throw() {
return ptr;
}
private:
void dispose() {
if (--*count == 0) {
delete count;
delete ptr;
}
}
};
struct comp {
int* Re, *Im;
comp() { Re = new int; Im = new int;;*Re = 0; *Im = 0; }
comp(int r, int i) { Re = new int; Im = new int;*Re = r; *Im = i; }
~comp() { delete Re; delete Im; }
const comp& operator=(const comp& T) { // оператор функция=
*Re = *T.Re; *Im = *T.Im; return *this;
}
const comp& operator-() { // оператор функция-
*Re = -*Re; *Im = -*Im; return *this;
}
comp(comp& T) { Re = new int; Im = new int; *Re = *T.Re; *Im = *T.Im;}
const comp operator*(const comp& T) { // оператор функция*
comp Rez(0,0);
*Rez.Re =*Re * *T.Re - *Im * *T.Im;
*Rez.Im = *Re * *T.Im + *Im * *T.Re;
return Rez;
}
double modComp()const {return sqrt(*Re**Re + *Im**Im); }
bool operator<(const comp T) { // оператор функция<
if(modComp() < T.modComp()) return 0;//х<х всегда ложно
return 1;
}
void comp::display() const
{
cout << "\n Re = " << *Re << "\t Im = " << *Im;
}
};
bool operator< (const CountedPtr<comp> p1, const CountedPtr<comp> p2) {
if (*p1 < *p2) return 0;
return 1;
}
void printCountedPtr(CountedPtr<comp> elem)
{
(*elem).display();
}
int main()
{
// Три разные коллекции
typedef CountedPtr<comp> IntPtr;
deque<IntPtr> coll1;
list<IntPtr> coll2;
set<IntPtr> coll3;
/* Вставка общих объектов в коллекции*/
for (int i = 0; i<5; ++i) {
IntPtr ptr(new comp(i,i));
coll1.push_back(ptr); //coll1.push_back(comp(i,i));
coll2.push_front(ptr);
coll3.insert(ptr);
}
// Вывод содержимого коллекций
cout<<"\n deque";
for_each(coll1.begin(),coll1.end(), printCountedPtr);
cout << "\n list";
for_each(coll2.begin(), coll2.end(), printCountedPtr);
cout << "\n set";
for_each(coll3.begin(), coll3.end(), printCountedPtr);
cout << endl << endl;
/* Модификация значений в разных коллекциях
* - возведение в квадрат значения в coll1
* - изменение знака первого значения в coll2
*/
*coll1[1] = *coll1[1] * *coll1[1];
// *coll2.front() = - (*coll2.front());
// Повторный вывод содержимого коллекций
cout << "\n\n deque";
for_each(coll1.begin(), coll1.end(), printCountedPtr);
cout << "\n list";
for_each(coll2.begin(), coll2.end(), printCountedPtr);
cout << "\n set";
for_each(coll3.begin(), coll3.end(), printCountedPtr);
cout << endl;
}
2.2. Упростите программу. Перейдите от ссылочной семантики к семантике по значению (класс CountedPtr не нужен). Сравните данные, выводимые на экран, упрощённой программой и исходной.
2.3. Определите свой собственный класс (например: запись в базе данных, строка, вектор, квадрат, круг) и сформируйте коллекции из объектов вашего класса.
Содержание отчета
3.1 Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.
3.2 Выполненное домашнее задание.
3.3 Тексты программ, написанные при выполнении 2.2 и 2.3 пунктов лабораторного задания.
Вопросы к защите
4.1. Какие типы коллекций вы знаете?
4.2. Сравните коллекции между собой. Какие у каждой из них имеются достоинства и недостатки?
4.3. Что такое итератор? Какие типы итераторов вы знаете?
4.4. Напишите программу реализующую список элементов типа квадрат.
4.5. Напишите программу, реализующую вектор комплексных чисел.
4.6. Напишите программу, реализующую набор строк.
4.7. Напишите программу, реализующую дек элементов типа эллипс.
4.8. Напишите класс «круг» вписанный в «квадрат», используя классы ClsEllipse и Square.
4.9. Напишите класс «текст» вписанный в «круг», используя классы ClsEllipse и DrowTxt.
4.10. Напишите класс «магазин», который работает с объектами абстрактного класса «товар». Определите 2-3 класса, производных от класса «товар». Продемонстрируйте примеры полиморфного поведения.
4.11. Напишите класс «вагон», который работает с объектами абстрактного класса «груз». Определите 2-3 класса, производных от класса «груз». Продемонстрируйте примеры полиморфного поведения.
Литература
1. Подбельский В. В. Стандартный Си++ [Текст]: учеб. пособие для студ. вузов. - М.: Финансы и статистика, 2008. - 687 с.: ил.. - Библиогр.: с. 667-669 (31 назв.). - ISBN 978-5-279-03243-3
2. Максимов М. Н. Язык Си++ как инструмент для моделирования радиотехнических цепей и сигналов [Текст]: курс лекций: для студ. радиотехн. спец. всех форм обуч.. Ч. 1 / ТТИ ЮФУ, РТФ, Каф. ТОР. - Таганрог: Изд-во ТРТУ, 2007. - 159 с.. - Библиогр.: с. 159 (5 назв.)
3. Библиотека STL