Указания к выполнению работы
Задание 1. Перегрузка функций
Написать программу, которая для базы сотрудников выдает по запросу список сотрудников либо родившихся раньше заданного года, либо имеющих оклад больше введенного с клавиатуры.
Варианты выборки из базы по различным запросам оформим в виде перегруженных функций. Мы от природной лени и для простоты рассматриваем базу с минимальным количеством полей; в реальных ситуациях их может быть гораздо больше, соответственно, больше будет и вариантов перегруженных функций. Также оформим в виде отдельной функции чтение базы из файла – и для лучшего структурирования программы, и для того, чтобы в случае необходимости было легче заменить эту функцию на другую, например, на чтение из бинарного файла.
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#include <iomanip.h>
const int I_name = 30, l_year = 5, l_pay = 10, l_buf = I_name + l_year + l_pay;
struct Man {
int birth_year; char name[l_name + 1];
float pay;
}
int read_dbase(const char * filename, Man dbase[ ], const int l_dbase,
int &n_record);
void print(Man m);
void select(Man dbase[ ], const int n_record, const int year);
void select(Man dbase[ ], const int n_record, const float pay);
int main(){
const int l_dbase = 100;
Man dbase[l_dbase];
int n_record = 0;
if (read_dbase( "txt6.txt", dbase, l_dbase, n_record) != 0 ) return 1;
int option;
int year;
float pay;
do {
cout << "----------------------------------- " << endl;
cout << "1 - Сведения по году рождения" << endl;
cout << "2 - Сведения по окладу" . << endl;
cout << "3 - Выход" << endl;
cin >> option;
switch (option) {
case 1: cout << "Введите год "; cin >> year;
select(dbase, n_record, year); break;
case 2: cout << "Введите оклад "; cin >> pay;
select(dbase, n_record, pay); break;
case 3: return 0;
default: cout << "Надо вводить число от 1 до 3" << endl;
} •. '-.У"
} while (true);
return 0;
}
void select(Man dbase[ ], const int n_record, const int year) {
cout << " Вывод сведений по году рождения" << endl;
bool success = false;
for (int i = 0; i < n_record; i++)
if (dbase[i],birth_year >= year) {
print (dbase[i]); success = true;
}
if (!success) cout << " Таких сотрудников нет" <<endl;
}
void select(Man dbase[ ], const int n_record, const float pay ){
cout << " Вывод сведений по окладу" << endl;
bool success = false;
for (int i = 0; i < n_record; i++)
if (dbase[i].pay >= pay) {
print (dbase[i]); success = true;
}
if (!success) cout << " Таких сотрудников нет" << endl;
}
void print(Man m) {
cout.setf(ios::fixed);
cout.precision(2);
cout << setw(40) << m.name << ' ' << m.btrth_year << ' ' <<
m.pay << endl;
}
int read_dbase( const char * filename, Man dbase[ ], const int l_dbase.
int &n_record) {
char buf [l_buf + 1];
ifstream fin(filename, ios::in | ios: :nocreate);
if (!fin ){ cout << "Нет файла " << filename << endl; return 1; }
int i =0;
while (fin.getline(buf, l_buf)) {
strncpy(dbase[i].name, buf, l_name);
dbase[i].name[l_name] = '\0';
dbase[i].birth_year = atoi(&buf[l_name]);
dbase[i].pay = atof(&buf[l_name + l_year]);
i++ ;
if (i > l_dbase) {cout << "Слишком длинный файл"; return 2; }
}
n_record = i;
fin.close();
return 0;
}
Добавьте в базу еще одно-два осмысленных поля (например, отдел, стаж или количество детей) и напишите еще одну перегруженную функцию для выборки по новому критерию. Если тип критерия будет такой же, как один из рассмотренных, то, чтобы компилятор мог различать варианты, можно добавить в функцию дополнительный параметр.
Ниже приведены правила описания перегруженных функций.
Перегруженные функции должны находиться в одной области видимости, иначе произойдет сокрытие аналогично одинаковым именам переменных во вложенных блоках.
Перегруженные функции могут иметь параметры по умолчанию, при этом значения одного и того же параметра в разных функциях должны совпадать. В различных вариантах перегруженных функций может быть различное количество параметров по умолчанию.
Функции не могут быть перегружены, если описание их параметров отличается только модификатором const или использованием ссылки.
Задание 2. Шаблоны функций
Написать программу, которая определяет максимальные элементы в одномерных массивах различных арифметических типов.
Поиск максимума – весьма распространенная задача, и желание сделать для этого универсальную функцию естественно. Для этого достаточно простейшего шаблона с одним параметром-типом. В саму функцию будет передаваться два аргумента: указатель на массив и длина этого массива.
#include <iostream.h>
#include <string.h>
template <class T> Т Max(T *b, int n);
int main(){
const int n = 20;
int i, b[n];
cout << "Введите " << n << " целых чисел:" << endl;
for (i =0; i < n; i++) cin >> b[i];
cout << Max(b, n) << endl;
double а[ ] = (0.22, 117.2, -0.08, 0.21, 42.5);
cout << Max(a, 5) << endl;
char *str = "Sophisticated fantastic template";
cout << Max(str, strlen(str)) << endl;
return 0;
}
template <class T> Т Max(T *b, int n) {
int imax = 0;
for (int i = 1; i < n; i++)
if (b[i] > b[imax]) imax = i;
return b[imax];
}
Шаблон функции имеет имя Мах. После ключевого слова template в угловых скобках перечисляются все параметры шаблона. В данном случае параметр один. При инстанцировании шаблона (в данном случае – неявном), то есть когда компилятор будет создавать конкретный вариант функции, этот тип будет заменен конкретным стандартным или пользовательским типом. Соответствие устанавливается при вызове функции либо по типу аргументов, либо по явным образом указанному типу. Например, последний вызов функции можно записать так:
cout << Max<char>(str, strlen(str));
Этот способ применяется в тех случаях, когда тип не определяется по виду оператора вызова функции.
Аналогично обычным параметрам функции, можно задавать значение параметра шаблона по умолчанию.
ВНИМАНИЕ: При работе с многофайловым проектом нужно не забывать, что если какой-то шаблон функции имеет инстанцирование в нескольких исходных файлах, то определение этого шаблона должно повторяться в каждом из этих файлов. Поэтому обычно определение шаблона выносят в заголовочный файл и подключают его в нужных местах директивой #include.
Давайте повторим основные моменты этой лабораторной работы.
Перегрузкой функций называется использование нескольких функций с одним именем и различными типами параметров.
Перегрузка применяется, когда одно и то же по смыслу действие реализуется по-разному для различных типов или структур данных.
При написании перегруженных функций необходимо, чтобы в процессе поиска нужного варианта функции по ее вызову не возникало неоднозначности. Неоднозначность может возникнуть из-за преобразований типов, параметров по умолчанию и ссылок.
Функции не могут быть перегружены, если описание их параметров отличается только модификатором const или использованием ссылки.
Шаблоны функций применяются для записи идентичных действий над данными различных типов.
Инстанцирование шаблона функции – это создание компилятором конкретного варианта функции.
Шаблоны можно перегружать как шаблонами, так и обычными функциями.
