орентирование 2кр. лб2. Лабораторная работа 2 по дисциплине объектноориентированное программирование Выполнил студент специальности 27. 03. 04
Скачать 0.52 Mb.
|
Министерство науки и высшего образования Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР) Лабораторная работа № 2 по дисциплине «ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ» Выполнил студент: специальности 27.03.04 Жуков Сергей Андреевич 2022 год Содержание 1.Задание………………………………………………………………………………3 2.Работа программы…………………………………………………………………..7 3.Листинг программ………………………………………………………………8-16 4.Заключение………………………………………………………………………..16 Вариант №9 ?????? Задание: Создание динамического массива объектов. Деструктор объекта. Два типа полиморфизма: принудительное приведение типа, перегрузка функций и перегрузка операторов (унарных и бинарных). В среде программирования на С++ создайте консольный проект с именем LAB2 в каталоге LAB2. Переименуйте файл main.h из предыдущей лабораторной в person.h. Создайте файл person.cpp, и включите в проект эти два файла. Переместите конструктор и функции объекта Person из main.cpp в файл person.cpp. Таким образом, файл person.h содержит описание объекта Person, а файл person.cpp – реализацию объекта Person. Включите в проект файл main.cpp и очистите тело функции main(). Определите объект Group, который будет содержать динамический массив объектов Person. Создайте два файла group.h и group.cpp и включите их в проект. В файле group.h определите с помощью ключевого слова classобъект Group. Данные объекта: размер массива (целый тип) указатель на массив (тип Person* ) Пусть данные имеют закрытый уровень доступа (private). Опишите конструктор объекта с одним аргументом – размер массива (целый тип) и деструктор объекта. Откройте файл group.cpp. С помощью директивы #includeвключите необходимые заголовочные файлы. Определите конструктор объекта Group. В теле конструктора проинициализируйте данные объекта, т.е. проинициализируйте размер массива значением аргумента конструктора и выделите динамическую память под массив с помощью строки кода: указатель на массив = new Person[размер массива]. В деструкторе объекта освободите память, занимаемую массивом, с помощью строки кода delete [] указатель на массив. Таким образом, мы создали объект Group, который содержит массив объектов Person. Определим открытые (public) методы для объекта Group. Напишите функцию void Group::Print(), которая выводит в цикле for все записи массива на экран. В теле цикла примените ранее написанную функцию Print() для объекта Person. Напишите функцию int Group::Size(), которая возвращает размер массива. Напишите функции void PutPerson(int i, Person& man); и Person& GetPerson(int i);, первая функция заносит объект man типа Person в i-й элемент массива, вторая функция возвращает объект типа Person из i-го элемента массива. Заполните массив данными и затем выведите их на экран. Для этого в теле функции int main() сначала определите массив имен, которые будут заносится в поле ФИО объекта Person, например, char names[5][25] = {"A", "B", "C", "D", "E"};. Затем создайте объект с именем group типа Group размером пять записей, т.е. Group group(5);. Ниже с помощью цикла for заполните массив данными. Для этого в теле цикла создайте объект Person, проинициализировав всеего данные, и с помощью функции PutPerson занесите объект в массив. Выведите массив на экран с помощью строки кода: group.Print();. Получилось? Если да, то вы научились создавать динамический массив объектов, определять функции работы с таким массивом и выводить его на экран. В этой части лабораторной работы изучим первые два типа полиморфизма – это: а) принудительное приведение типа; б) перегрузка функций и операторов. Напишите функцию приведения типа. Для этого с помощью ключевого слова operator напишите функцию объекта Person, которая преобразует тип Person вdouble. Пусть функция возвращает возраст человека, например, Person::operator double() {returnthis->Age; }. Что означает ключевое слово this? Проверьте функцию преобразования типа. В функции int main() далее определите переменную double и присвойте ей объект Person, например, double age = group.GetPerson(2);. Т.е. совершается неявное преобразование из типа Person в тип double при обращении к объекту. Выведите значение переменной на экран. Перегруженные функции имеют одинаковое название, но разный возвращаемый тип или/и разный список аргументов. Определим в объекте Group две функции с одинаковым именем, например double Age(); и double Age(int limit);. Первая функция пусть возвращает средний возраст группы людей, а вторая функция пусть возвращает средний возраст людей в группе, возраст которыхне больше некоторого граничного значения limit. Функции отличаются списком аргументов. Проверьте работу перегруженных функций, отобразив на экране подсчитанные два значения среднего возраста. Перегрузите оператор индексирования. Если раньше, чтобы обратиться к элементу массива, нам необходимо было вызывать функцию GetPerson, то, определив оператор индексирования, мы будем использовать только квадратные скобки. Сравните две строки кода: Person man = group.GetPerson(2); Person man = group[2]; В объекте Group с помощью ключевого слова operator определите оператор индексирования, например: Person& Group::operator[](int i). В теле оператора напишите код, возвращающий i-тый элемент массива, т.е. объект Person Выведите на экран с помощью оператора индексирования любой один элемент массива group, например третий. Перегрузим бинарный оператор, например оператор сложения (+) для объекта Person. Пусть оператор сложения будет возвращать суммарный возраст двух человек. Опишем в объекте Person данный оператор как дружественную функцию с помощью ключевого слова friend, например: friend double operator+(Person& p1, Person& p2); Эта строка кода означает, что оператор сложения не принадлежит объекту, но ему доступны все закрытые данные и методы объекта. В файле person.cpp определите оператор сложения, например: doubleoperator + (Person& p1, Person& p2) { return (p1.Age + p2.Age); } Здесь мы напрямую обращаемся к закрытому полю Age объекта Person. Проверим работу оператора с помощью следующих строк кода: double sum = group[1] + group[3]; cout << sum << endl Работа программы: Листинг программы : Person.h #include class Person { public: // данные имеют открытый уровень доступа //конструктор объекта, аргументы которого инициализируют все его данные Person(int number, const char* fio, int man_woman, double age); //конструктор объекта по умолчанию Person(); //функция вывода данных на экран void Print() const; //функция ввода данных в объект с клавиатуры void Input(); //приведение к типу double. возвращает возраст operator double() const; //получить значение номера int GetNumber() const; //получить фио const char* GetFio() const; //проверить женщина ли это int IsWoman() const; //проверить мужчина ли это int IsMan() const; //получить возвраст double GetAge() const; //оператор сравнения двух объектов типа Person bool operator==(Person const& other) const; //оператор неравенства bool operator!=(Person const& other) const; //оператор вывода в поток (дружественная функция) friend ostream& operator <<(ostream& os, Person const& pers); private: // данные имеют закрытый уровень доступа int _number; // номер человека char _fio[64];// Ф.И.О. int _man_woman;// пол double _age; // возраст }; Person.cpp #include #include #include #include "person.h" //конструктор объекта, аргументы которого инициализируют все его данные Person::Person(int number, const char* fio, int man_woman, double age) : _number(number),_man_woman(man_woman),_age(age)//установка простых полей { strncpy(_fio,fio,sizeof(_fio));//копирование Ф.И.О. } //конструктор объекта по умолчанию Person::Person() : _number(0),_man_woman(0),_age(0)//установка простых полей { _fio[0] = 0;//т.к. первый символ равен 0,в Ф.И.О. пустая строка } //функция вывода данных на экран void Person::Print() const { cout << *this;//вызывает оператор << } //функция ввода данных в объект с клавиатуры void Person::Input() { cout << "Input new person data:" << endl;//приглашение ввести данные о новом человеке cout << "\tInput number: ";//приглашение ввести номер человека cin >> _number;//ввод номера cout << "\tInput name: ";//приглашение ввести Ф.И.О. человека cin.ignore(); //пропуск символа конца строки cin.getline(_fio,sizeof(_fio),'\n');//ввод Ф.И.О. человека cout << "\tInput age: ";//приглашение ввести возраст cin >> _age;//ввод возраста cout << "\tInput sex(0 - man, else - woman): ";//приглашение ввести пол cin >> _man_woman;//ввод пола } //приведение к типу double. возвращает возраст Person::operator double() const { return _age; } //получить значение номера int Person::GetNumber() const { return _number; } //получить фио const char* Person::GetFio() const { return _fio; } //проверить женщина ли это int Person::IsWoman() const { return _man_woman; } //проверить мужчина ли это int Person::IsMan() const { return !_man_woman; } //получить возвраст double Person::GetAge() const { return _age; } //оператор сравнения двух объектов типа Person bool Person::operator==(Person const& other) const { return _number == other._number && _age == other._age && _man_woman == other._man_woman && 0 == strcmp(_fio, other._fio); } //оператор неравенства bool Person::operator!=(Person const& other) const { return !(*this == other);//инвертируем результат оператора == } //оператор вывода в поток (дружественная функция) ostream& operator <<(ostream& os, Person const& pers) { os << "Num: " << pers._number << "\tName: " << pers._fio << "\tAge: " << pers._age << "\tSex: " << (pers._man_woman?'W':'M') << endl; return os; } Main.cpp #include "group.h" #include #include //главная функция int main() { Group g1(5);//группа 1 g1.PutPerson(0,Person(1,"Roman Romanov ", 0, 35.0)); g1.PutPerson(1,Person(2,"Stepan Stepanov ", 0, 25.0)); g1.PutPerson(2,Person(3,"Petr Petrov ", 0, 60.0)); g1.PutPerson(3,Person(4,"Ivan Ivanov ", 1, 22.0)); g1.PutPerson(4,Person(5,"Maksim Maksimov ", 0, 21.0)); //1. демонстрация работы оператора << //вывод группы на экран cout << "Group #1\n" << g1 << endl; //2. демонстрация работы оператора сравнения групп //создаём копию группы 1 Group g2(g1.Size()); for(unsigned i=0;i g2.PutPerson(i,g1[i]);//копируем поэлементно. //вывод группы на экран cout << "Group #2\n" << g2 << endl; //вывод результата сравнения cout << "G1 is equal to G2: it is " << ((g1 == g2)?"true":"false") << endl << endl; g2.PutPerson(3, Person(6,"Vasya ", 0, 40)); //теперь группы должны отличаться cout << "Group #2\n" << g2 << endl; cout << "G1 is equal to G2: it is " << ((g1 == g2)?"true":"false") << endl << endl; //3. демонстрация функций поиска в группе Person* result = 0; const int NUMBER = 2; const int WRONGNUMBER = 33; result = g1.FindPerson(NUMBER);//по номеру cout << "Search for number "< if(result) cout << *result; else cout << "" << endl; result = g1.FindPerson(WRONGNUMBER);//по номеру (которого нет) cout << "Search for number "< if(result) cout << *result; else cout << "" << endl; const double AGE = 22.0; const double WRONGAGE = 33.3; result = g1.FindPerson(AGE);//по возрасту cout << "Search for age "< if(result) cout << *result; else cout << "" << endl; result = g1.FindPerson(WRONGAGE);//по возрасту (которого нет) cout << "Search for age "< if(result) cout << *result; else cout << "" << endl; const char* const NAME = "Maksim Maksimov "; const char* const WRONGNAME = "NEKTO"; result = g1.FindPerson(NAME);//по возрасту cout << "Search for name \""< if(result) cout << *result; else cout << "" << endl; result = g1.FindPerson(WRONGNAME);//по имени (которого нет) cout << "Search for name \""< if(result) cout << *result; else cout << "" << endl; cout << "Press any key for exit..." << endl; getch();//ожидание нажатия любой клавиши return EXIT_SUCCESS;//завершение работы программы } GROUP.h #ifndef GROUP_H #define GROUP_H #include "person.h" //класс "Группа" class Group { private: unsigned _size;//размер массива Person* _persons;//указатель на массив элементов типа Person public: //секция открытых методов //конструктор с указанием размера Group(unsigned size); //деструктор Group(); //выводит данные о всех хранимых элементах void Print() const; //возвращает размер массива unsigned Size() const; //вставить элемента в указанную позицию void PutPerson(int idx, Person const& man); //получить ссылки на элемент в указанной позиции Person const& GetPerson(int idx) const; //средний возраст double Age() const; //средний возраст среди лиц не старше limit double Age(int limit) const; //перегруженный оператор [] //получение ссылки на элемент в указанной позиции Person& operator[](int idx); //оператор сравнения двух групп bool operator==(Group const& other) const; //искать по номеру Person* FindPerson(int number); //искать по имени Person* FindPerson(const char* fio); //искать по возрасту Person* FindPerson(double age); }; //оператор вывода в поток ostream& operator <<(ostream& os, Group const& g); #endif Group.cpp //Файл с реализацией методов класса Group #include "group.h" #include //конструктор // size - размер создаваемого массива. Group::Group(unsigned size) : _size(size) //запоминаем размер массива , _persons(size ? new Person[size] : 0) //выделяем память, если надо {} //деструктор Group::Group() { delete[] _persons;//освобождение памяти из-под массива } //выводит данные о всех хранимых элементах void Group::Print() const { cout << *this;//искользуем оператор << } //возвращает размера массива unsigned Group::Size() const { return _size; } //вставить элемента в указанную позицию void Group::PutPerson(int index, Person const& man) { _persons[index] = man; } //получить ссылки на элемент в указанной позиции Person const& Group::GetPerson(int index) const { return _persons[index]; } //получить средний возраст в группе double Group::Age() const { double sum = 0;//сумма for (unsigned i = 0; i < _size; ++i) sum += _persons[i];//вызывается оператор приведения к double return _size ? sum/_size : 0; } //средний возраст вреди лиц не старше limit double Group::Age(int limit) const { double sum = 0;//сумма всех возрастов unsigned count = 0;//количество подсчитанных элементов for (unsigned i = 0; i < _size; ++i) { if(_persons[i] <= limit)//сравниваем с ограничением по возрасту { sum += _persons[i]; ++count; } } return count ? sum/count : 0; } //перегруженный оператор [] - получение ссылки на элемент в указанной позиции Person& Group::operator[](int index) { return _persons[index]; } //оператор сравнения двух групп bool Group::operator==(Group const& other) const { if(_size != other._size) return false;//не равны размеры for(unsigned i = 0; i < _size; ++i) if(_persons[i] != other._persons[i])//используем оператор != из класса Person return false;//найдены неравные элементы return true;//все элементы оказались равны } //искать по номеру Person* Group::FindPerson(int number) { for(unsigned i = 0; i < _size; ++i) if(number == _persons[i].GetNumber()) return _persons+i; return 0;//ничего не найдено } //искать по имени Person* Group::FindPerson(const char* fio) { for(unsigned i = 0; i < _size; ++i) if(0 == strcmp(fio, _persons[i].GetFio())) return _persons+i; return 0;//ничего не найдено } //искать по возрасту Person* Group::FindPerson(double age) { for(unsigned i = 0; i < _size; ++i) if(age == _persons[i].GetAge()) return _persons+i; return 0;//ничего не найдено } //оператор вывода в поток ostream& operator <<(ostream& os, Group const& g) { for(unsigned i = 0; i < g.Size(); ++i) os << "Person #" << i << ":\n"<< g.GetPerson(i); os << (g.Size() ? "" : "empty") << endl; return os; } Заключение Видим что программа отработала хорошо и все данные вывела на экран . |