Лабораторная

Лабораторная работа №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. Какие классы и функции называются дружественными?

  2. Как осуществляется перегрузка операций?

  3. Сколько аргументов требуется для определения перегруженной унарной (бинарной) операции?

  4. Чем отличается действие перегруженной операции ++ при ее использовании в префиксной форме от использовании в постфиксной форме?

Порядок выполнения лабораторной работы

Напишите программу согласно Вашему варианту задания с использованием проектов.

Варианты заданий

Номер
варианта

Задание

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