КаталогИндекс раздела
НазадОглавлениеВперед


Лабораторная работа ╧2
Перегрузка операторов в языке С++

1. Цель работы

Целью лабораторной работы является получение практических навыков в использовании перегрузки операторов в языке С++.

2. Темы для предварительного изучения

3. Варианты индивидуальных заданий

Смотри лабораторную работу ╧2 (части I).

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

4. Задание к выполнению

Задание к выполнению аналогично заданию в лабораторной работе ╧10 (части I), но программа должна быть составлена с использованием класса, необходимо предусмотреть функции доступа к полям класса (функции get() и set()) и необходимо перегрузить следующие операторы:

5. Пример решения задачи (вариант 30).

5.1. Разработка алгоритма решения.

Алгоритм программы линейный и его программная реализация не представляется затруднительной.

5.2. Описание структуры класса.

5.2.1. Описание полей класса.

Для выполнения условий задания нам потребуется класс с функциями-аксессорами из предыдущей лабораторной работы. Напомним, что класс, описывающий Буддистские монастыри Японии имеет следующие поля:

5.2.2. Функции - члены класса и дружественные функции.

Класс church имеет следующие функции-члены:


Класс church имеет следующие дружественные функции:

5.3. Разработка текста программы

Для удобства работы с программой введ╦м переменную-константу, которая будет отвечать за количество экземпляров класса church. То есть будем работать с массивом объектов класса church размерностью N.

#define N 3

Перейд╦м к описанию объявленных выше функций:

Отметим, что функции set, get, show взяты из предыдущей лабораторной работы и остались без изменений.

church operator = (church &o1);
Данная функция производит перегрузку оператора присваивания, то есть выполняет присваивание полей одного объекта класса полям другого объекта этого же класса. При перегрузке бинарного оператора левый операнд переда╦тся функции неявно, а правый переда╦тся в качестве аргумента. Возвращаемый тип - сам класс, т.е church. Как и в предыдущей лабораторной работе для корректной работы со строками требуется динамическое выделение памяти и е╦ освобождение. В целом эта функия - аналог функции set.

int operator == (church &o1);
Функция позволяет установить соответствие между экземплярами одного класса. Т.е. е╦ тело включает проверку на равенство значений числовых полей и сравнение содержимого строк, которое выполняется с помощью функции strcmp. В зависимости от того, тождественны ли экземпляры функцией возвращается 0 или 1.

church operator + (church &o1);
Функция operator+() возвращает объект типа church Отметим тот факт, что временный объект tr используется внутри функции operator+() для хранения результата и является возвращаемым объектом. Отметим также, что ни один из операндов не меняется. Назначение переменной tr легко понять.

В данной ситуации (как и в большинстве ситуаций) оператор + был перегружен способом, аналогичным своему традиционному арифметическому использованию. Поэтому и было важно, чтобы ни один из операндов не менялся. Например, когда вы складываете 10+4, результат равен 14, но ни 10, ни 4 не меняются. Таким образом, временный объект необходим для хранения результата.

friend ostream & operator<<(ostream &stream, church &o1);
Первый параметр является ссылкой на объект типа ostream. Это означает, что поток stream должен быть потоком вывода. Второй параметр получает выводимый объект. (Он, если для вашего приложения это нужно, тоже может быть параметром-ссылкой). Обратите внимание, что пользовательская функция вывода возвращает ссылку на поток stream, который имеет тип ostream. Это необходимо, если перегруженный оператор << должен использоваться в ряде последовательных выражений ввода/вывода.

friend istream & operator>>(istream &stream, church &o1);
Пользовательские функции ввода возвращают ссылку, на поток istream, который является потоком ввода. Первый параметр тоже является ссылкой на поток ввода. Второй параметр ≈ это ссылка на объект, получающий вводимую информацию.

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

friend void shapka(void);
Данная функция является вспомогательной. Она формирует шапку таблицы при вызове перегруженной формы оператора <<

friend int isvalid(int a, int b);
Функция, описанная выше выполняет проверку данных, которые вводит пользователь. Т.е проверяет соответствие номеров класса на существование.

     Полный текст программы приведен ниже.


Лабораторная работа ╧2
Перегрузка операторов в языке C++.
Вариант ╧30
Пример выполнения


#include <iostream.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <iomanip.h>
#define N 3             //количество экземпляров класса

class church {
 char *name;
 char *school;
 unsigned int count;
 float square;
 friend ostream & operator<<(ostream &stream, church &o1);
 friend istream & operator>>(istream &stream, church &o1);
 friend void shapka(void);
 friend void linebuild(void);
 friend int isvalid(int a, int b);
public:
 church() { square=0; count=0;}
 church(char *a, char *b, unsigned int &c, float &d);
 void setall(char *a,char *b,unsigned int ,float );
 void getall(char *a, char *b, unsigned int &c, float &d);
 void showall(void);
 church operator = (church &o1);
 int    operator == (church &o1);
 church operator + (church &o1);
};

 ostream & operator<<(ostream &stream, church &o1) {
  shapka();
  stream<<"|"<<setw(10)<<o1.name<<"  |  ";
  stream<<setw(5)<<o1.school<<"|";
  stream<<setw(18)<<o1.count<<"  |";
  stream<<setw(17)<<o1.square<<"  |"; endl;
  linebuild();
 return stream;
 }

istream & operator>>(istream &stream, church &o1) {
 cout<<"Название, Школа, Количество монахов, Площадь земли: \n";
 stream>>o1.name;
 stream>>o1.school;
 stream>>o1.count;
 stream>>o1.square;
 return stream;
}

int isvalid(int a, int b){
  if (((a>N-1) || (a<0)) || ((b>N-1) ||(b<0)))
   {
    cout<<"Ошибка! Экземпляра с таким индексом не существует.\n";
    getch();
    return -1;
   }
  else if (a==b)
   {
    cout<<"Ошибка! Экземпляр не может быть записан сам в себя.\n";
    getch();
    return -2;
   }
 return 0;
}

church church::operator + (church &o1) {
	church tr;
	int i,j;
 delete[] tr.name;
 delete[] tr.school;
 tr.name=new char [strlen(name)+strlen(o1.name)+2]; 
 strcpy(tr.name,name);
 strcat(tr.name, o1.name);
 tr.school=new char [strlen(school)+strlen(o1.school)+2]; 
 strcpy(tr.school,school);
 strcat(tr.school, o1.school);
 tr.count=count+o1.count;
 tr.square=square+o1.square;
 return tr;
}

int church::operator == (church &o1) {
 if (count != o1.count) {cout << "Данные экземпляры класса не равны."; getch();}
 else if (ceil(square)!=ceil(o1.square)) {cout << "Данные экземпляры класса не равны."; getch();}
 else if (strcmp(name,o1.name) != 0) {cout << "Данные экземпляры класса не равны."; getch();}
 else if (strcmp(school,o1.school) != 0) {cout << "Данные экземпляры класса не равны."; getch();}
 else cout<<"Экземпляры класса равны."; getch();
 return 0;
}

church church::operator = (church &o1) {
 delete [] name;
 delete [] school;
 name = new char [strlen(o1.name)+2];
  if (!name) {
   cout<<"Ошибка! Память не выделена.";
   exit(1);
  }
 strcpy(name,o1.name);
 school = new char [strlen(o1.school)+2];
  if (!school) {
   cout<<"Ошибка! Память не выделена.";
   exit(1);
  }
 strcpy(school,o1.school);
 count = o1.count;
 square = o1.square;
 return o1;
}

church::church(char *a, char *b, unsigned int &c, float &d) {
 name=new char [strlen(a)+1];
 strcpy(name,a);
 school=new char [strlen(b)+1];
 strcpy(school,b);
 count=c;
 square=d;
}

void church::setall(char *a,char *b,unsigned int c,float d) {
 strcpy(name,a);
 strcpy(school,b);
 count=c;
 square=d;
}

void church::showall(void) {
 cout<<name<<" ";
 cout<<school<<" ";
 cout<<count<<" ";
 cout<<square<<" ";
}

void church::getall( char * a, char *b, unsigned int &c, float &d)
{
 delete[] a;
 delete[] b;
 a=new char [strlen(name)+1];
 b=new char [strlen(school)+1];
 strcpy(a,name);
 strcpy(b,school);
 c=count;
 d=square;
 cout<<a<<" ";
 cout<<b<<" ";
 cout<<c<<" ";
 cout<<d<<" ";
 cout<<"\n";
}

void shapka(void)
{
 cout<<"_______________________________________________________________\n";
 cout<<"|         Буддистские монастыри Японии периода Нара           |\n";
 cout<<"|-------------------------------------------------------------|\n";
 cout<<"|  Название  | Школа | Количество монахов | Площадь земли(га) |\n";
 cout<<"|-------------------------------------------------------------|\n";
 }

void linebuild(void) {
 cout<<"\n|-------------------------------------------------------------|\n";
}

int main(void) {
	char *n;
	char *t;
	unsigned int s;
	float h;
	short i,k;
	unsigned int s1;
	short q,q1;

	church obj[N]={church("Тодайдзи","Т",220,368.8),
		       church("Якусидзи","С",50,54.7),
		       church("Дайандзи","Д",10,12.2)};
 clrscr();
 cout.precision(2);
 cout<<"Название, Школа, Количество монахов, Площадь земли: \n";
 for (i=0; i<N; i++) {
  obj[i].showall();
  cout<<"\n";
  }

 cout<<"\nПерегрузка оператора присваивания '='.\n";
 cout<<"Введите номера экземпляров класса: заменяемый и заменяющий>\n";
 cin>>q;
 cin>>q1;
 if (isvalid(q, q1)!=0) exit(-1);
 obj[q] = obj[q1];  

  cout<<"Название, Школа, Количество монахов, Площадь земли: \n";
  for(i=0; i<N; i++) {
   obj[i].showall();
   cout<<"\n";
  }

 cout<<"\nПерегрузка оператора соответствия '=='.\n";
 cout<<"Введите номера экземпляров класса, которые надо сравнить>\n";
 cin>>q;
 cin>>q1;
 if (isvalid(q, q1)!=0) exit(-1);
 obj[q] == obj[q1];  

 cout<<"\nПерегрузка оператора суммы '+'.\n";
 cout<<"Введите номера экземпляров класса, которые надо сложить>\n";
 cin>>q;
 cin>>q1;
 church temp;
 if (isvalid(q, q1)!=0) exit(-1);
 temp=obj[q]+obj[q1];  
   cout<<"Наименование, Тип, Посевная площадь, Урожайность: ";
   temp.getall(n,t,s,h);

 cout<<"\nПерегрузка оператора потокового ввода '>>'.";
 cout<<"\nВведите номер экземпляра класса: ";
 cin>>q;
 if ((q>N-1)||(q<0)) {cout<<"Ошибка! Экземпляра с таким индексом не существует."; getch(); exit(-1);}
 cin>>obj[q]; 

 cout<<"\nПерегрузка оператора потокового вывода '<<'.";
 cout<<"\nВведите номер экземпляра класса: ";
 cin>>q;
 if ((q>N-1)||(q<0)) {cout<<"Ошибка! Экземпляра с таким индексом не существует."; getch(); exit(-1);}
 cout<<obj[q]; 

 getch();
 return 0;
}

НазадОглавлениеВперед
КаталогИндекс раздела