Файл: Основные понятия объектно-ориентированного программирования (Модификация).pdf

ВУЗ: Не указан

Категория: Курсовая работа

Дисциплина: Не указана

Добавлен: 04.04.2023

Просмотров: 88

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Следовательно, после того, как все эти сведения найдены и обработаны, можно определиться с теми сущностями, которые потребуются.

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

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

На этом заканчивается этап анализа: были выделены основные сущности, определены первоначальные требования к функциональности и определены границы проекта, были описаны абстракции.

Следующий этап - этап проектирования. Теперь всю информацию, полученную во время анализа необходимо переработать в практические данные.

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

Структура будет иметь такой вид:

struct matrix{ // структура для матрицы

int size; // порядок матрицы

int *_array; // целочисленный массив

};

А класс для графа следующий:

class Graph { // рабочий класс

private:

int arr_size; // порядок матрицы

int *arr; // целочисленный массив

bool is_cycle; // найден ли цикл

int *poseshenie; // счетчик посещений вершины

bool *mark ; // массив меток

public:

Graph(matrix *g); // конструктор

Graph(Graph &T); // конструктор для копии

void Graph::DFS(int v); // функция обхода

void Set(matrix*g); // связывает объект задачи с графом g и выполняет решение задачи для графа g

void Restart(); // повторно выполняет решение задачи для графа g

bool Result(); // результат

~Graph(); // деструктор

};

Объявления классов и структур содержится в заголовочном файле graph.h, а вот их определения - в файле graph.cpp.

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

Начать следует с реализации конструкторов и деструктора класса графа. Первый конструктор как параметр должен принимать матрицу, а второй - создавать копию объекта.

Graph::Graph(matrix *g){ // конструктор с параметром-матрицей


this->arr_size = g->size;

poseshenie = new int [arr_size];

mark = new bool [arr_size];

if (g->size>0){

arr = new int[g->size*g->size];

memcpy(arr,g->_array,sizeof(int)*(g->size)*(g->size));

}

else arr=NULL;

this->Restart();

}

Graph::Graph(Graph &T){ // конструктор, создающий копию объекта

this->arr_size = T.arr_size;

poseshenie = new int [arr_size];

mark = new bool [arr_size];

if (this->arr_size>0){

arr = new int[T.arr_size*T.arr_size];

memcpy(arr,T.arr,sizeof(int)*(T.arr_size)*(T.arr_size));

}

else arr= NULL;

this->Restart();

}

Graph::~Graph(){ // деструктор

arr_size =0;

delete [] arr;

delete [] poseshenie;

delete [] mark;

}

После реализации и подключения этих методов следует перейти к тем, которые, собственно, отвечают за решение задачи, а именно:

1. Функция обхода графа.

void Graph::DFS(int v){

int i;

bool tmp=true;

mark[v]=true;

poseshenie[v]++;

///тут проверка на обход единожды

for (i=0; i<arr_size; i++)

if ((!mark[i])||(poseshenie[i]!=1)) {

tmp=false;

break;

}

if (tmp) is_cycle = true;

///

for (i=0; i<arr_size; i++){

if (arr[v*arr_size+i]==1)

if(mark[i]==0){

DFS(i);

poseshenie[v]++;

}

}

}

2. Функция, которая связывает объект задачи с графом g и выполняет решение задачи для графа g.

void Graph::Set(matrix*g){

this->arr_size = g->size;

if (g->size>0){

arr = new int[g->size*g->size];

memcpy(arr,g->_array,sizeof(int)*(g->size)*(g->size));

}

else arr=NULL;

this->Restart();

}

3. Функция, которая повторно выполняет решение задачи для графа g.


void Graph::Restart(){

is_cycle = false;

if (arr_size<1) return;

int i, v;

for (v=0; v<arr_size; v++){

for (i=0; i<arr_size; i++){

poseshenie[i]=0;

mark[i]=false;

}

DFS(v);

}

}

И функция, возвращающая результат:

bool Graph::Result(){

return is_cycle;

}

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

Для этого необходимо еще две вспомогательные функции - случайная генерация матрицы и её вывод на экран.

/* случайная генерация матрицы */

void rnd_matrix(int &size,int maxsize, int ** matr){

if (maxsize<2) return;

srand(int(time(NULL)));

size = 2+ rand()%(maxsize-1);

*matr = new int [sizeof(int)*size*size];

for (int i=0;i<size*size;i++)

if (rand()<16000)

(*matr)[i]=rand()%2;

else (*matr)[i]=0;

}

/* вывод матрицы на экран */

void print_matrix(int size,int *matr){

for (int i =0;i<size;i++){

for (int j=0;j<size;j++)

printf("%2d",matr[i*size+j]);

printf("\n");

}

}

В итоге главная функция программы принимает следующий вид:

int main()

{

matrix a;

rnd_matrix(a.size,10,&a._array);

printf("Sourse 1 graph-matrix-\n");

print_matrix(a.size,a._array);

Graph g(&a);

if (g.Result()) printf("True\n");

else printf("False\n");

g.Set(&a); //проверка процедуры сет

Graph g1(g); //конструктор копирования

int *p = new int [4] ;

matrix b = {2,p}; //тестовый пример матрицы 2х2

b._array[0]= 0; b._array[1]= 1;


b._array[2]= 0; b._array[3]= 0;

printf("Sourse 2 graph-matrix-\n");

print_matrix(2,b._array);

Graph g2(&b);

if (g2.Result()) printf("True\n");

else printf("False\n");

p = new int [9];

matrix c = {3,p}; //тестовый пример матрицы 3x3

for (int i = 0;i<9;i++) c._array[i]=0;

c._array[1]= 1; c._array[5]= 1;

printf("Sourse 3 graph-matrix-\n");

print_matrix(3,c._array);

Graph g3(&b);

if (g3.Result()) printf("True\n");

else printf("False\n");

_getch();

return 0;

}

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

На рисунках ниже (3.1 и 3.2) показан результат работы программы. Здесь матрица графа сгенерирована случайно (3 раза) и показаны результаты расчета для каждого из них.

рис.3.1.

рис.3.2.

Заключение

В данной курсовой работе была рассмотрена парадигма объектно-ориентированного программирования, а также этапы объектно-ориентированного программирования.

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

Во второй главе теоретической части был рассмотрен собственно объект исследования - этапы объектно-ориентированного программирования. Как было установлено, всего выделяют четыре этапа, каждый из которых был тщательно проанализирован и объяснен. Было предоставлено обоснование, почему именно эти этапы необходимо пройти при разработке программного обеспечения и использованием объектно-ориентированного подхода к программированию. Первый этап - этап анализа - одинаков для любого подхода, ясно, что без анализа поставленной задачи нельзя переходить к её программной реализации, этот этап скорее теоретический, чем практический. Второй этап - этап проектирования - уже больше относится к объектно-ориентированному программированию, а вот третий уже целиком и полностью объектно-ориентирован. Никакая другая парадигма программирования не использует эволюцию для создания программы - это особенность именно объектно-ориентированного программирования. Этап модификации может быть в различных подходах, однако именно в объектно-ориентированном он наиболее прост и лёгок в исполнении, что даёт большое преимущество перед, например, функциональным или процедурным программированием.


Третья глава - глава практики, было рассмотрено на примере, как именно применяются в реальной жизни теория, а именно как помогает наличие четкого плана при создании программного продукта. Была создана программа, основанная на принципах объектно-ориентированного программирования в языке С++.

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

Вместо таких структур программ, как код и данные, объектно-ориентированная система объединяет эти два понятия в новое - понятие «объекта». Объект имеет состояние (данные) и поведение (код). Объекты соответствуют вещам, найденным в реальном мире. Так, например, графическая программа будет иметь объекты, такие как круг, квадрат, меню. Онлайновая система магазина содержит объекты, такие как корзина, клиент, продукт.

Целями объектно-ориентированного программирования являются:

  • более глубокое понимание;
  • простота обслуживания;
  • простота эволюции.

Используя объектно-ориентированный подход очень важно не забывать про основные этапы разработки программного обеспечения, а это анализ, проектирование, эволюция и модификация.

Список литературы

1. Е. А. Роганов - «Основы информатики и программирования» - Москва, 2001 - 299 с.

2. Тимоти Бадд - «Объектно-ориентированное программирование».

3. Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес - «Приёмы объектно-ориентированного программирования. Паттерны программирования» - Санкт-Петербург, 2001 - 352 с.

4. А. Пол - «Объектно-ориентированное программирование на С++».