Лабораторная работа №14 Перегрузка операторов Дружественные классы
Разрешить элементам другого класса полный доступ к элементам данного класса, объявленным как private или protected, можно включив в определение данного класса описание friend.
Пример 14.1.
сlass myclass
{ friend class another_class; };
Дружественные функции
Разрешить обычной функции или функции-элементу другого класса полный доступ к элементам класса, объявленным private или protected, можно с помощью описания friend в определении данного класса.
Пример 14.2.
сlass myclass
{ friend void another_class::member(int);
friend void func_name(float);
};
Для друзей существуют следующие правила:
-
на описания friend не влияют спецификаторы public, protected или private;
-
описания friend не взаимны: если А объявляет В другом, то это не означает, что А является другом для В;
-
дружественность не наследуется: если А объявляет В другом, классы, производные от В, не будут автоматически получать доступ к элементам А;
-
дружественность не является переходным свойством: если А объявляет В другом, классы, производные от А, не будут автоматически признавать дружественность В.
Перегрузка операций
Язык С++ позволяет определять и применять к классам обозначения операций. Эта особенность, называемая перегрузкой операций дает классам возможность вести себя подобно встроенному типу данных.
Операции, допускающие перегрузку:
+ * / % ^ & | ~ ! = < > += = *= /= %= ^= &=
|= << >> <<= >>= == != <= >= && || ++ >* > () [ ]
Функции-операции и перегрузка операций подчиняются следующим правилам:
-
приоритеты операций и правила ассоциации, принятые для встроенных типов данных, остаются неизменными при оценке выражений с перегруженными функциями-операциями;
-
функция-операция не может изменить поведение операции по отношению к встроенным типам данных;
-
функция-операция должна быть либо элементом класса, либо воспринимать один или несколько аргументов, имеющих тип класса;
-
функция-операция не может иметь аргументов по умолчанию;
за исключением operator=() функции-операции наследуются.
Примеры программирования
Пример 14.4.
Описать и определить класс-список, операцию –, как сортировка списка по убыванию и операцию [ ] получения значения по заданному номеру.
Файл list.h содержит описание класса.
struct list
{ int inf; // информационное поле
list *next; // указатель на следующий элемент списка
};
class spisok
{ list* l; // указатель на начало списка
public:
spisok (int);
spisok (spisok&);
void print ();
int operator [ ](int);
friend void operator - (spisok&);
~spisok();
};
Файл list.cpp содержит определение функций-элементов.
#include "stdafx.h"
#include <stdlib.h>
#include "list.h"
#include <iostream>
#include <iomanip>
using namespace std;
spisok::spisok (int n)
//конструктор инициализирует список из n элементов по принципу
// "очередь"
{ l = NULL;
list *p,*pn;
for (int i = 0; i<n; i++)
{ p = new list;
p->inf = rand()%100-50;
p->next = NULL;
if (l == NULL) l = p;
else pn->next = p;
pn = p;
}
}
spisok::spisok (spisok& s)
//конструктор копии класса spisok
{ l = NULL;
list *sp = s.l, *p, *pn;
while (sp)
{ p = new list;
p->inf = sp->inf;
p->next = NULL;
if (l == NULL) l = p;
else pn->next = p;
pn = p;
sp = sp->next;
}
}
spisok::~spisok()
//деструктор - уничтожает объект класса список из памяти
{ list *p;
while ( l )
{ p = l;
l = l->next;
delete p;
}
}
void spisok::print()
//функция-элемент печати содержимого списка
{ list *p = l;
while (p)
{
cout<<setw(4)<<p->inf;
p = p->next;
}
cout<<endl;
}
int spisok::operator [ ] (int n)
//перегруженная операция получения значения по заданному номеру n
{ list *p = l;
for (int i = 1; (i<n )&& (p!=NULL); i++, p = p->next);
if (p) return p->inf;
return -1000;
}
void operator - (spisok& s)
//дружественный перегруженный оператор сортировки элементов
// списка по убыванию
{ list *p = s.l;
while (p)
{ list *max = p, *pn = p->next;
while (pn)
{ if (pn->inf > max->inf) max = pn;
pn = pn->next;
}
int i = max->inf;
max->inf = p->inf;
p->inf = i;
p = p->next;
}
}
Файл main.cpp содержит основную функцию.
#include "stdafx.h"
#include "list.h"
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
srand((unsigned)time(NULL));
setlocale(LC_ALL, "Russian");
spisok s1(10), // создание списка из 10 элементов
s2(s1), // s2- копия списка s1
s3(15); // создание списка из 15 элементов
s1.print(); // печать s1
s2.print(); // печать s2
s3.print(); // печать s3
cout<<"Значение третьего элемента в s1="<<s1[3]<<endl;
-s3; // сортировка s3
s3.print(); // и печать его
_getch();
return 0;
}
В проект включены файлы: main.cpp и list.cpp, list.h.