Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Основы объектно-ориентированного программирования задач на графах. Учебное пособие
.pdf
6.3. Унарная функция-операция для проверки смежности двух вершин графа
51
но, и имена переменных, соответствующих номерам двух вершин, во всех
функциях класса должны быть изменены, т.е. замените x11 на x1, а x22 на
x2.
Изменим и главную функцию для вызова рассмотренных функцийопераций:
//---------------------------------------------------#pragma argsused
int main()
{
int number;
int x1,x2;
cin>>number;
My_Class * graph = new My_Class(number);
+(*graph); // ввод матрицы смежности графа
-(*graph); // вывод матрицы смежности графа
cout<<" Input number of two tops: ";
cin>>x1>>x2;
graph->adjacency(x1,x2);
graph->Graph::adjacency(x1,x2);
*(*graph); //ввод номеров двух вершин
cout<< endl<<" Tops ";
// проверка смежности двух вершин
if( !(*graph)) cout<<" Adjacent";
else cout<< " No Adjacent";
delete graph;
getch();
return 0;
}
//----------------------------------------------------
Перегрузка операции (!) демонстрирует также возможность возвращения
значения функциями-операциями.

6. Задачи на графах и перегрузка операций
52
6.4. Перегрузка операций для виртуальных функций
Как быть в случае, если необходимо перегрузку операций использо-
вать для виртуальных функций? В нашем примере виртуальные функции
adjacency() в классах Graph и My_Class, имеющие два аргумента,
заменим функциями-операциями operator++() без аргументов, аналогично тому, как это было сделано в предыдущем примере для функцииоперации для определения смежности двух вершин. Замените объявление
виртуальной функции
virtual void adjacency(int,int);
в описании класса Graph на
virtual void operator++();
а объявление витуальной функции
void adjacency(int,int);
в описании класса My_Class на
void operator++();
Замените также заголовки в определении виртуальных функций. В результате получим описания классов Graph и My_Class, содержащие виртуальные функции-операции operator++(). В классе Graph виртуальная
функция-операция operator++() определяет вершины графа, смежные
хотя бы одной из двух заданных вершин графа. В классе My_Class виртуальная функция-операция operator++() определяет вершины графа,
смежные одновременно каждой из двух заданных вершин графа. Добавьте в главную функцию операторы для ввода номеров двух вершин:
*(*graph);
и вызова функции-операции operator++() с помощью перегруженной операции (++):
++(*graph);
Если запустить программу на выполнение, то результатом примене-
ния перегруженной операции (++) к объекту класса My_Class будет вы-

6.4. Перегрузка операций для виртуальных функций
53
звана последняя в иерархии классов Graph и My_Class виртуальная
функция-операция operator++(), т.е. функция-операция
operator++() из класса My_Class. На экран будут выведены номера
вершин графа, смежные одновременно каждой из двух заданных вершин
графа.
Но как быть, если требуется вызвать виртуальную функциюоперацию operator++() с помощью перегруженной операции (++) из
класса Graph? Это сделать не удастся. Вызвать виртуальную функциюоперацию operator++() из базового класса можно только обычным вызовом виртуальной функции класса:
graph->Graph::operator++();
В результате главная функция будет иметь вид:
int main()
{
int number;
cin>>number;
My_Class * graph = new My_Class(number);
+(*graph); // ввод матрицы смежности графа
-(*graph); // вывод матрицы смежности графа
*(*graph); //ввод номеров двух вершин
++(*graph);
graph->Graph::operator++();
*(*graph); //ввод номеров двух вершин
cout<< endl<<" Tops ";
if( !(*graph)) cout<<" Adjacent";
else cout<< " No Adjacent";
delete graph;
getch();
return 0;
}
Полный текст программы, в которой все функции классов Graph и
My_Class оформлены с использованием перегрузки операций, приведен в
прил. 4.

6. Задачи на графах и перегрузка операций
54
6.5. Результат выполнения программы для унарных операций
На рис. 11 приведен результат работы программы для графа
(см. рис. 6). Начало ввода данных осталось за пределами окна.
Рис. 11. Результат работы программы для графа (см. рис. 6)
6.6. Бинарные функции-операции
Бинарная функция-операция создается для двух операндов. Один
операнд должен быть обязательно объектом класса. Второй операнд может
быть объектом того же класса, что и первый операнд, или данным встроенного типа.
Бинарная функция-операция должна иметь один обязательный аргу-
мент. Тип этого аргумента зависит от того, какой второй операнд образует
эту операцию. Если бинарная функция-операция класса создается для двух
объектов одного и того же класса, то аргумент должен быть ссылкой или
указателем на объект этого же класса. Если вторым операндом является
встроенный тип данных, то тип аргумента должен совпадать с типом второго операнда.
Зачем нужен обязательный аргумент? Дело в том, что функцияоперация – это функция класса. Как и каждой функции класса, ей неявно
передается указатель this на первый объект, который образует бинар-

6.7. Бинарная функция-операция для определения вершин, смежных заданной…
55
ную операцию. Этот указатель обеспечит доступ к данным и функциям
объекта класса, соответствующего первому операнду. Доступ к членам
второго операнда (объекта класса или данного встроенного типа) функцияоперация получит только через обязательный аргумент.
6.7. Бинарная функция-операция для определения вершин,
смежных заданной вершине графа
Для решения задач на графах создадим две новые функции-операции:
вывода на экран номеров вершин, смежных заданной вершине, и объединения двух графов с одинаковым числом вершин. Для первой задачи перегрузим операцию сравнения (>), а для второй задачи – логическую операцию «ИЛИ» (||).
Прототип функции-операции
void operator>(int);
первой задачи добавьте в описание класса My_Class:
class My_Class : public Graph
{
public: void operator*(); //ввод номеров двух
//вершин
int operator!(); //проверка смежности двух
//вершин
My_Class(int a ):Graph(a){}
void operator++();
void operator>(int);
};
Определение этой функции сделайте вне класса:
void My_Class::operator>(int x)
{
cout<<" Set of Tops adjacent top "<<x<<": {";
for(int i=0; i<N; i++)

6. Задачи на графах и перегрузка операций
56
if(Matr[x-1][i])
cout<<" "<<i+1<<",";
cout<<" }";
}
Функция-операция имеет один аргумент – целое число, соответству-
ющее номеру вершины, для которой требуется определить вершины с ней
смежные.
В главную функцию добавьте операторы:
//------- вершины смежные с заданной вершиной -------
cout<<endl<<"Input number of tops: ";
int x1;
cin>>x1;
(*graph)>x1; //бинарная операция (>)
Обратите внимание, что в бинарной перегруженной операции (>)
(*graph)>x1;
для объекта класса My_Class первым должен быть обязательно расположен операнд – объект класса My_Class, а вторым – данное встроенного
целого типа.
6.8. Бинарная функция-операция для объединения двух графов
Объединение графов – это операция над графами, в результате кото-
рой получается граф, множества вершин и рёбер которого являются объединениями множеств вершин и рёбер исходных графов, т.е. в результирующий граф входят все рёбра и вершины, которые присутствуют в исходных графах.
Для обединения двух графов потребуется создать два объекта класса,
которые будут задавать исходные графы. В каждом объекте класса будет
функция объединения двух графов. Тогда возникает необходимость передачи одного объекта в функцию объединения графа, того объекта, для которого эта функция будет вызываться.

6.8. Бинарная функция-операция для объединения двух графов
57
В С++ объекты классов передаются в функции классов через указа-
тель или ссылку на объект класса. Рассмотрим способ передачи объектов
классов в функции классов посредством указателя на объект класса.
Создадим перегруженную функцию-операцию для объединения двух
графов. Для этого добавим в описание класса My_Class прототип функции-операции operator||():
void operator||(My_Class *);
Обратите внимание, что функция-операция имеет обязательный аргумент – указатель на объект класса My_Class.
Выбор знака встроенной операции || (побитовой операции включающего «ИЛИ»), связан исключительно с ассоциациями, которые возникают при рассмотрении операции объединения двух графов.
Определение этой функции сделайте вне класса:
//---функция вывода на экран объединения двух графов
void My_Class :: operator||(My_Class * graph_2)
{
//выделение динамической памяти для матрицы смежности
//объединенного графа
bool **union_matr;
union_matr=new bool *[N];
for(int i=0; i<N;i++)
union_matr[i]= new bool [N];
//построение матрицы смежности объединенного графа
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
if(Matr[i][j]||graph_2->return_ij(i,j))
union_matr[i][j]=1;
else union_matr[i][j]=0;
//вывод на экран матрицы смежности объединенного
графа
cout<<endl<<"Matrix of Union Graph";

6. Задачи на графах и перегрузка операций
58
for(int i=0; i<N; i++)
{
cout<<endl;
for(int j=0; j<N; j++)
cout<<union_matr[i][j]<<" ";
}
//удаление из динамической памяти матрицы смежности
//объединенного графа
for(int i=0; i<N;i++)
delete[] union_matr[i];
delete[] union_matr;
}
В этой функции-операции создается в динамической памяти двумерный массив с указателем union_matr для матрицы смежности объединенного графа. Построение матрицы смежности объединенного графа заключается в просмотре элементов двумерных массивов двух объектов одного и того же класса My_Class. Один массив с указателем Matr соответствует
объекту, который будет расположен первым в записи перегруженной операции (||). Элементы второго массива будут видны в функции-операции
за счет аргумента этой функции – указателя на объект класса My_Class.
Этому аргументу будет присвоен адрес объекта, который будет расположен
вторым в записи перегруженной операции (||).
Поскольку указатель Matr является личным данным класса Graph,
то доступ к нему возможен только с помощью функций этого класса. Поэтому необходимо создать дополнительно функцию, которая возвращает
значение элемента массива с указателем Matr. Эта функция должна иметь
два аргумента, соответствующих индексам элементов массива. Назовем эту
функцию return_ij(). Функция простая, поэтому определим ее в теле
класса My_Class:
class My_Class : public Graph
{
public: void operator*(); //ввод номеров двух вершин
int operator!(); //проверка смежности двух
//вершин

6.8. Бинарная функция-операция для объединения двух графов
59
My_Class(int a):Graph(a){}
void operator++();
void operator>(int);
void operator||(My_Class *);
int return_ij(int i,int j){return
Matr[i][j];}
};
Добавьте в главную функцию операторы для создания второго объ-
екта класса My_Class:
My_Class * graph_1 = new My_Class(number);
для ввода матрицы смежности второго графа:
+(*graph_1);
а также опреатор вывода на экран матрицы смежности объединения двух
графов:
(*graph)||graph_1;
Обратите внимание, что первый операнд в бинарной операции (||)
должен быть обязательно объект класса, а не указатель. Это связано с правилом использования перегрузки операций для объектов классов, по которому прегрузка операций применяется только для объектов классов. Поэтому для указателя graph на объект, соответствующий первому графу,
применена операция взятия содержимого по адресу (*). Второй операнд –
указатель на объект класса, соответствующий второму графу, так как при
создании функции-операции operator||() выбран в качестве аргумента
указатель на объект класса My_Class.
Окончательно главная функция теперь будет такой:
int main()
{
int number;
cout <<" Input number of Graph Tops: ";
cin>>number;

6. Задачи на графах и перегрузка операций
60
My_Class * graph = new My_Class(number);
+(*graph); // ввод матрицы смежности первого графа
-(*graph); // вывод матрицы смежности графа
*(*graph); //ввод номеров двух вершин
++(*graph);
graph->Graph::operator++();
*(*graph); //ввод номеров двух вершин
cout<< " Tops ";
if( !(*graph)) cout<<" Adjacent";
else cout<< " NO Adjacent";
//-- вершины смежные с заданной вершиной ------
cout<<endl<<" Input number of top: ";
int x1; cin>>x1;
(*graph)>x1;
//создание второго объекта
My_Class * graph_1 = new My_Class(number);
// ввод матрицы смежности второго графа
+(*graph_1);
//вывод на экран матрицы смежности объединения двух
//графов
(*graph)||graph_1;
delete graph;
getch();
return 0;
}
Полный текст программы приведен в прил. 5.
6.9. Пример выполнения программы для бинарных функций-операций
Для графов, представленных на рис. 12 и рис. 14, матрицы смежности
показаны соответственно на рис. 13 и рис. 15. На рис. 16 показан граф, полученный в результате объединения этих графов. Матрица смежности показана на рис. 17.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
