Лабораторная работа №14 / 14_перегрузка_a5.doc
Лабораторная работа №14
Перегрузка функций. Перегрузка операторов
Цель работы: 1) изучить возможности программирования классов на языке С++; 2) получить основные навыки программирования.
Теоретические сведения
Дружественные классы
Разрешить элементам другого класса полный доступ к элементам данного класса, объявленным как 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 не взаимны: если А объявляет В другом, то это не означает, что А является другом для В;
дружественность не наследуется: если А объявляет В другом, классы, производные от В, не будут автоматически получать доступ к элементам А;
дружественность не является переходным свойством: если А объявляет В другом, классы, производные от А, не будут автоматически признавать дружественность В.
Перегрузка функций-элементов
Функции-элементы класса могут быть перегружены. Две или несколько функций-элементов могут иметь одно и тоже имя, при условии, что списки их аргументов не совпадают.
Пример 14.3.
class Time
{ char timestr[30];
public:
Time(); // перегрузка конструкторов
Time(char *str);
};
Перегрузка операций
Язык С++ позволяет определять и применять к классам обозначения операций. Эта особенность, называемая перегрузкой операций дает классам возможность вести себя подобно встроенному типу данных.
Операции, допускающие перегрузку:
+ − * / % ^ & | ~ ! = < > += −= *= /= %= ^= &=
|= << >> <<= >>= == != <= >= && || ++ −− −>* −> () [ ]
Функции-операции и перегрузка операций подчиняются следующим правилам:
приоритеты операций и правила ассоциации, принятые для встроенных типов данных, остаются неизменными при оценке выражений с перегруженными функциями-операциями;
функция-операция не может изменить поведение операции по отношению к встроенным типам данных;
функция-операция должна быть либо элементом класса, либо воспринимать один или несколько аргументов, имеющих тип класса;
функция-операция не может иметь аргументов по умолчанию;
за исключением 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 <stdlib.h>
#include <stdio.h>
#include "list.h"
spisok::spisok (int n)
//конструктор инициализирует список из n элементов по принципу
// "очередь"
{ l = NULL;
list *p,*pn;
for (int i = 0; i<n; i++)
{ p = new list;
p−>inf = random(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)
{ printf ("%3d ",p−>inf);
p = p−>next;
}
puts("");
}
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 <stdio.h>
#include “list.h”
void main (void)
{ spisok s1(10), // создание списка из 10 элементов
s2(s1), // s2- копия списка s1
s3(15); // создание списка из 15 элементов
s1.print(); // печать s1
s2.print(); // печать s2
s3.print(); // печать s3
printf("Значение третьего элемента в s1=%d \n",s1[3]);
-s3; // сортировка s3
s3.print(); // и печать его
}
В проект включены файлы: main.cpp и list.cpp.
Результаты выполнения программы:
-49 -50 -17 -47 -15 -29 3 -31 20 44
-49 -50 -17 -47 -15 -29 3 -31 20 44
-23 -6 -40 19 6 -46 -34 31 18 26 32 45 -29 -8 45
Значение третьего элемента в s1=−17
45 45 32 31 26 19 18 6 -6 -8 -23 -29 -34 -40 -46
Пример 14.5.
Описать и определить класс файл и операции:
= копирование файлов;
-- определение самой короткой строки в файле.
Файл описания класса file.h
class file
{ char *name; // имя файла
FILE *f; // указатель на поток
public:
file (char *, char *); // конструктор
file &operator = (file &); // операция копирования файлов
friend char* operator --(file &); // операция поиска
// наименьшей строки
~file() // деструктор
{ fclose(f);delete name;
};
};
Файл определения функций-элементов file.cpp
#include <stdio.h>
#include <string.h>
#include "file.h"
file::file(char *n, char *attr) //конструктор - открывает файл
{ name = new char[strlen(n)+1];
strcpy (name, n);
f=fopen (name, attr);
}
file& file::operator = (file &f1) //операция копирования файла
{ char stroka[120];
fseek (f1.f,0,0);
while (fgets (stroka, 120, f1.f))
fputs (stroka, f);
return *this;
}
char* operator -- (file &f1) //дружественная операция поиска
// наименьшей строки в файле
{ fseek(f1.f, 0, 0);
char *sent = new char[120];
int minlen = 120;
char stroka[120];
while (fgets(stroka, 120, f1.f))
if (strlen(stroka)<minlen)
{ minlen = strlen(stroka);
strcpy (sent, stroka);
}
return sent;
}
Файл main_f.cpp с основной функцией.
#include <stdio.h>
#include "file.h"
void main(void)
{ file f1("test1.txt", "rt"), // открытие файла для чтения
f2("test2.txt", "wt"); // открытие файла для записи
f2 = f1; //копирование файлов
printf("Самая короткая строка = %s\n",f1--);
}
Проект содержит файлы main_f.cpp и file.cpp.
Контрольные вопросы
Какие классы и функции называются дружественными?
Как осуществляется перегрузка операций?
Сколько аргументов требуется для определения перегруженной унарной (бинарной) операции?
Чем отличается действие перегруженной операции ++ при ее использовании в префиксной форме от использовании в постфиксной форме?
Порядок выполнения лабораторной работы
Напишите программу согласно Вашему варианту задания с использованием проектов.
Варианты заданий
Номер | Задание |
1, 16 | Определить класс-строку. В класс включить два конструктора: для определения класса строки строкой символов и путем копирования другой строки (объекта класса строки). Определить операции над строками: >> перевертывание строки (запись символов в обратном порядке); ++ нахождение наименьшего слова в строке. |
2, 17 | Определить класс-строку. В класс включить два конструктора: для определения класса строки строкой символов и путем копирования другой строки (объекта класса строки). Определить операции над строками: ++ преобразование символов строки в прописные (заглавные) символы; -- нахождение самого короткого слова в строке. |
3, 18 | Определить класс-строку. В класс включить два конструктора: для определения класса строки строкой символов и путем копирования другой строки (объекта класса строки). Определить операции над строками: + конкатенация двух строк; ++ преобразование символов строки в строчные (маленькие) символы. |
Номер | Задание |
4, 19 | Определить класс-строку. В класс включить два конструктора: для определения класса строки строкой символов и путем копирования другой строки (объекта класса строки). Определить операции над строками: - удаление одной строки из другой ( если одна строка является подстрокой другой); -- преобразование символов строки в строчные (маленькие) символы. |
5, 20 | Определить класс список элементов. В определение класса включить два конструктора: для определения списка по его размеру и путем копирования другого списка. Определить операции над списком: | формирование нового списка из двух списков так, что каждый элемент информационного поля нового списка удовлетворяет условию: с=(а > b ) ? a : b Определить функцию-элемент класса для вставки нового элемента в список на определенное место. |
6, 21 | Определить класс список элементов. В определение класса включить два конструктора для определения списка по его размеру и путем копирования другого списка. Определить операции над списком: & формирование нового списка из двух списков так, что каждый элемент информационного поля нового списка удовлетворяет условию: с=(а < b ) ? a : b Определить функцию-элемент класса для удаления элемента с определенного места списка. |
7, 22 | Определить класс список элементов. В определение класса включить два конструктора для определения списка по его размеру и путем копирования другого списка. Определить операции над списком: ++ сортировка списка по возрастанию; -- расположение элементов списка в обратном порядке. |
Номер | Задание |
8, 23 | Определить класс список элементов. В определение класса включить два конструктора для определения списка по его размеру и путем копирования другого списка. Определить операции над списком: [ ] получение значения информационного поля указанного элемента списка; - удаление из первого списка элементов второго, если второй список входит в первый. |
9, 24 | Определить класс список элементов. В определение класса включить два конструктора для определения списка по его размеру и путем копирования другого списка. Определить операции над списком: + конкатенация двух списков; & формирование нового списка из двух списка так, что каждый элемент информационного поля нового списка удовлетворяет условию: с=(а > b ) ? a : b |
10, 25 | Определить класс матрицу. В класс включить два конструктора для определения матрицы по количеству элементов и путем копирования другой матрицы. При задании матрицы предусмотреть ее заполнение случайными числами. Определить операции над матрицей: ++ нахождение наибольшего значения матрицы; + получение новой матрицы, каждый элемент которой равен сумме соответствующих элементов двух других матриц. |
11, 26 | Определить класс матрицу. В класс включить два конструктора для определения матрицы по количеству элементов и путем копирования другой матрицы. При задании матрицы предусмотреть ее заполнение случайными числами. Определить операции над матрицей: -- нахождение наименьшего значения матрицы; - получение новой матрицы, каждый элемент которой равен разности элементов двух других матриц. |
Номер | Задание |
12, 27 | Определить класс стек. В класс включить два конструктора для определения стека по его размеру и путем копирования другого стека. Определить операции над стеком: + поместить элемент в стек; -- удалить элемент из стека. Определить две функции-элемента класса для выдачи на экран текущего элемента стека и содержимого стека. |
13, 28 | Определить класс вектор. В класс включить два конструктора для определения вектора по его размеру и путем копирования другого вектора. При задании вектора по его размеру предусмотреть его заполнение случайными числами. Определить операции над векторами: & формирование нового вектора так, что каждый элемент нового вектора определяется следующим образом: c[i]=(a[i]>b[i])?a[i]:b[i]; ++ определить наибольший элемент вектора. |
14, 29 | Определить класс вектор. В класс включить два конструктора для определения вектора по его размеру и путем копирования другого вектора. При задании вектора по его размеру предусмотреть его заполнение случайными числами. Определить операции над векторами: | формирование нового вектора так, что каждый элемент нового вектора определяется следующим образом: c[i]=(a[i]>b[i])?b[i]:a[i]; -- определить наименьший элемент вектора. |
15,30 | Определить класс вектор. В класс включить два конструктора для определения вектора по его размеру и путем копирования другого вектора. При задании вектора по его размеру предусмотреть его заполнение случайными числами. Определить операции над векторами: [ ] нахождение значения элемента вектора по заданному номеру; ++ сортировка элементов вектора по возрастанию. |
195
