Материал: ООП_Л_1

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Министерство образования Республики Беларусь

Министерство образования Республики Беларусь

БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ

Кафедра эконмической информатики

Объектно-ориентированное программирование

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

“Классы и объекты в языке C++”

Вариант 16

Выполнила: Студентка группы

972303

Рушева Маргарита

Владиславовна

Проверила: Григорьева Юлия

Юрьевна

Минск, 2020

1 Цель лабораторной работы

Изучить структуру класса, атрибуты доступа к компонентам класса; рассмотреть принцип работы конструкторов (с параметрами, без параметров, с параметрами по умолчанию, конструктора копирования), деструкторов при работе с объектом, статические и константные данные и методы класса.

2 Теория по лабораторной работе

КЛАСС в объектно-ориентированном программировании, представляет собой шаблон для создания объектов, обеспечивающий начальные значения состояний: инициализация полей-переменных и реализация поведения функций или методов. Объявление класса начинается с ключевого слова class. Объявление класса синтаксически подобно объявлению структуры. Основное отличие между С++-структурой и С++классом состоит в том, что по умолчанию элементы класса являются закрытыми, а элементы структуры — открытыми. В остальном же структуры и классы имеют одинаковое назначение. И классы, и структуры могут иметь сочетание открытых и закрытых элементов, могут использовать наследование и могут иметь функции-элементы. С++-программисты тип class используют главным образом для определения формы объекта, который содержит методы-элементы и данные, а тип struct — для создания объектов, которые содержат только элементы данных.

ОБЪЕДИНЕНИЕ (UNION) – тип данных, переменная которого может хранить (в разное время) объекты различного типа и размера. В результате появляется возможность работы в одной и той же области памяти с данными различного вида. Для описания объединения используется ключевое слово union. В языке С++ класс, определяемый посредством ключевых слов struct, class, union, включает в себя методы и данные, создавая новый тип объектов. Компоненты класса имеют ограничения на доступ.

Обычно данные класса имеют атрибут доступа private или protected, а методы – public. Значения атрибутов доступа:

private – элемент класса с атрибутом private может использоваться только методами собственного класса и функциями-«друзьями» этого же класса;

protected – тот же доступ, что и private, но дополнительно элемент класса может использоваться методами и функциями-«друзьями» производного класса, для которого данный класс является базовым;

public – элемент класса может использоваться любой функцией, т. е. защита на доступ к элементу снимается.

Элементы структуры (struct) и объединения (union) по умолчанию имеют доступ public.

Использование функций для установки начальных значений полей объекта часто приводит к ошибкам. КОНСТРУКТОР - функция, позволяющая инициализировать объект в процессе его декларирования (определения). Конструктор является элементом класса и имеет то же имя, что и класс. Конструктор может иметь и не иметь аргументы, но он никогда не возвращает значение (даже типа void). Класс может иметь несколько конструкторов, что позволяет использовать несколько различных способов инициализации объектов. Конструктор вызывается при создании объекта.

Конструктор, у которого все аргументы заданы по умолчанию, называется КОНСТРУКТОРОМ ПО УМОЛЧАНИЮ, т. е. конструктором, который можно вызывать без указания каких-либо аргументов.

Противоположные действия, по отношению к действиям конструктора, выполняет МЕТОД-ДЕСТРУКТОР или метод-разрушитель, который уничтожает объект. Деструктор может вызываться явно или неявно. Деструктор не может иметь аргументы, возвращать значение и наследоваться.

Подобно конструкторам деструкторы не возвращают значений, следовательно, в их объявлениях отсутствует тип возвращаемого значения. В отличие от конструкторов, деструкторы не могут иметь параметров.

УКАЗАТЕЛЬ THIS — это неявный параметр, принимаемый всеми методами-элементами класса. В любом методе-элементе класса указатель this можно использовать для ссылки на вызывающий объект.

Основные свойства и правила использования указателя this:

− каждый новый объект имеет свой скрытый указатель this;

− указатель this указывает на начало своего объекта в памяти компьютера;

− указатель this не надо дополнительно объявлять;

− указатель this передается как скрытый аргумент во все нестатические (т. е. не имеющие спецификатора static) компоненты-методы;

− указатель this является локальной переменной, которая недоступна за пределами объекта;

− можно обращаться к указателю this непосредственно в виде this или *this.

Ключевое различие между статической локальной и глобальной переменными состоит в том, что статическая локальная переменная известна только блоку, в котором она объявлена, а глобальная известна всему файлу. Таким образом, статическую локальную переменную в некоторой степени можно назвать глобальной переменной, которая имеет ограниченную область видимости. Чтобы объявить статическую переменную, достаточно предварить ее тип ключевым словом static. Локальные static-переменные инициализируются только однажды, в начале выполнения программы, а не при каждом входе в функцию, в которой они объявлены.

3 Индивидуальное задание

Построить систему классов для описания плоских геометрических фигур: круг, квадрат, прямоугольник. Предусмотреть методы для создания объектов, перемещения их на плоскости, изменения размеров фигур. Написать программу, демонстрирующую работу с этими классами. Программа должна содержать меню, позволяющее осуществить проверку всех методов классов. В класс добавить необходимый набор полей и методов (минимум два поля и два метода) на свое усмотрение. Предусмотреть метод для записи полученных данных в файл.

Рисунок 3.1 – Индивидуальное задание

4 Код решения индивидуального задания

figure.h”

#pragma once

#include <string>

#include <fstream>

using namespace std;

//класс Фигура - базовый для остальных классов

class Figure

{

protected:

double x, y; //координаты точки, определяющей положение фигуры (для окружности - центр, для прямоугольника - левый верхний угол)

string color; //цвет фигуры

public:

//конструктор, который будет вызываться в классах-наследниках

Figure(double x, double y, string color) { this->x = x; this->y = y; this->color = color; }

//методы перемещения фигуры и получения значений координат

void SetX(double x) { this->x = x; }

double GetX() { return this->x; }

void SetY(double y) { this->y = y; }

double GetY() { return this->y; }

string GetColor() { return this->color; } //узнать цвет

//виртуальные методы, которые будут перегружены в каждом классе

virtual double CalcSquare() = 0; //вычислить площадь

virtual double CalcPerimeter() = 0; //периметр

virtual void WriteToFile(ofstream& out) = 0; //запись данных в открытый файл

};

Circle.h”

#pragma once

#include "Figure.h"

//Круг наследуется от фигуры

class Circle :

public Figure

{

private:

double r; //радиус

public:

Circle(double x, double y, string color, double r);

void SetR(double r) { this->r = r; }

double GetR() { return r; }

double CalcSquare() override;

double CalcPerimeter() override;

void WriteToFile(ofstream& out) override;

};

Circle.cpp”

#include "Circle.h"

Circle::Circle(double x, double y, string color, double r) : Figure(x, y, color)

{

this->r = r;

}

double Circle::CalcSquare()

{

return 3.1415 * r * r; //площадь = пи * R^2

}

double Circle::CalcPerimeter()

{

return 2 * 3.1415 * r; //периметр = 2*пи * R

}

void Circle::WriteToFile(ofstream& out)

{

out << "Cirlce: (" << this->GetX() << "; " << this->GetY() << "). R: " << this->GetR() << endl;

}

Square.h”

#pragma once

#include "Figure.h"

//класс Квадрат наследуется от Фигуры

class Square :

public Figure

{

protected:

double a; //новое поле - длина стороны

public:

Square(double x, double y, string color, double a);

double GetA() { return this->a; };

void SetA(double a) { this->a = a; };

//перегружаемые методы

double CalcSquare() override;

double CalcPerimeter() override;

void WriteToFile(ofstream& out) override;

};

Square.cpp”

#include "Square.h"

//конструктор использует конструктор базового класса для координат и цвета

Square::Square(double x, double y, string color, double a) : Figure(x, y, color)

{

this->a = a;

}

double Square::CalcSquare()

{

return a * a;

}

double Square::CalcPerimeter()

{

return a * 4;

}

//запись данных в файл

void Square::WriteToFile(ofstream& out)

{

out << "Square: (" << this->GetX() << "; " << this->GetY() << "). a: " << this->GetA() << " " << endl;

}

Rectangle.h”

#pragma once

#include "Square.h"

//Прямоугольник наследуется от Квадрата

class RectangleF :

public Square

{

private:

double b; //добавляем ширину

public:

RectangleF(double x, double y, string color, double a, double b);

void SetB(double b) { this->b = b; }

double GetB() { return b; }

double CalcSquare() override;

double CalcPerimeter() override;

void WriteToFile(ofstream& out) override;

};

Rectangle.cpp”

#include "Rectangle.h"

RectangleF::RectangleF(double x, double y, string color, double a, double b) : Square(x, y, color, a)

{

this->b = b;

}

double RectangleF::CalcSquare()

{

return (this->a * this->b); //длина * ширина

}

double RectangleF::CalcPerimeter()

{

return (a + b) * 2;

}

void RectangleF::WriteToFile(ofstream& out)

{

out << "Rectangle: (" << this->GetX() << "; " << this->GetY() << "). a: " << this->GetA() << "; b: " << this->GetB() << endl;

}

FiguresProject.cpp”

#include <iostream>

#include <Windows.h>

#include "Rectangle.h"

#include "Circle.h"

int main()

{

SetConsoleOutputCP(1251);

SetConsoleCP(1251);

Figure* rct, * sq, * crl; //указатели для хранения данных о фигуре каждого класса

string color;

double a, b, r, x, y;

//начальный ввод данных о фигурах

cout << "Введите данные о квадрате\n";

cout << "Левая верхняя точка - x: ";

cin >> x;

cout << "Левая верхняя точка - y: ";

cin >> y;

cout << "Длина стороны: ";

cin >> a;

cout << "Цвет: ";

cin >> color;

sq = new Square(x, y, color, a); //создаем квадрат

cout << "\nВведите данные о прямоугольнике\n";

cout << "Левая верхняя точка - x: ";

cin >> x;

cout << "Левая верхняя точка - y: ";

cin >> y;

cout << "Длина: ";

cin >> a;

cout << "Ширина: ";

cin >> b;

cout << "Цвет: ";

cin >> color;

rct = new RectangleF(x, y, color, a, b); //создаем прямоугольник

cout << "\nВведите данные об окружности\n";

cout << "Центр - x: ";

cin >> x;

cout << "Центр - y: ";

cin >> y;

cout << "Радиус: ";

cin >> r;

crl = new Circle(x, y, color, r);

//вывод данных о фигурах

cout << "Кадрат, цвет: " << sq->GetColor() << ".\nЛевая верхняя точка: (" << sq->GetX() << "; " << sq->GetY() << ")\nДлина стороны: " << ((Square*)sq)->GetA() << endl;

cout << "\nПрямоугольник, цвет: " << rct->GetColor() << ".\nЛевая верхняя точка : (" << rct->GetX() << "; " << rct->GetY() << ")\nДлина: " << ((RectangleF*)rct)->GetA() << "; ширина: " << ((RectangleF*)rct)->GetB() << endl;

cout << "\nОкружность, цвет: " << crl->GetColor() << ".\nЦентр : (" << crl->GetX() << "; " << crl->GetY() << ")\nРадиус: " << ((Circle*)crl)->GetR() << endl;

//работа с фигурами через меню

int command = -1;

while (command != 0) //пока не выбран выход из программы

{

//вывод меню

cout << "\nМеню:\n";

cout << "1 - Вывод данных о фигурах\n";

cout << "\n2 - Переместить квадрат\n";

cout << "3 - Изменить размеры квадрата\n";

cout << "4 - Вычислить периметр и площадь квадрата\n";

cout << "\n5 - Переместить прямоугольник\n";

cout << "6 - Изменить размеры прямоугольника\n";

cout << "7 - Вычислить периметр и площадь прямоугольника\n";

cout << "\n8 - Переместить окружность\n";

cout << "9 - Изменить размеры окружность\n";

cout << "10 - Вычислить периметр и площадь окружности\n";

cout << "11 - Запись данных о фигурах в файл figures.txt\n";

cout << "0 - Выход\n";

cout << "\nВведите номер команды: ";

cin >> command;

cout << "\n";

//в зависимости от команды выполняем действие

switch (command)

{

case 1:

{

cout << "Кадрат, цвет: " << sq->GetColor() << ".\nЛевая верхняя точка: (" << sq->GetX() << "; " << sq->GetY() << ")\nДлина стороны: " << ((Square*)sq)->GetA() << endl;

cout << "\nПрямоугольник, цвет: " << rct->GetColor() << ".\nЛевая верхняя точка : (" << rct->GetX() << "; " << rct->GetY() << ")\nДлина: " << ((RectangleF*)rct)->GetA() << "; ширина: " << ((RectangleF*)rct)->GetB() << endl;

cout << "\nОкружность, цвет: " << crl->GetColor() << ".\nЦентр : (" << crl->GetX() << "; " << crl->GetY() << ")\nРадиус: " << ((Circle*)crl)->GetR() << endl;

break;

}

case 2:

{

cout << "Введите координаты для перемещения квадрата\n";

cout << "Левая верхняя точка - x: ";

cin >> x;

cout << "Левая верхняя точка - y: ";

cin >> y;

sq->SetX(x);

sq->SetY(y);

break;

}

case 3:

{

cout << "Введите длину стороны: ";

cin >> a;

((Square*)sq)->SetA(a);

break;

}

case 4:

{

cout << "Площадь квадрата: " << ((Square*)sq)->CalcSquare() << endl;

cout << "Периметр квадрата: " << ((Square*)sq)->CalcPerimeter() << endl;

break;

}

case 5:

{

cout << "Введите координаты для перемещения прямоугольника\n";

cout << "Левая верхняя точка - x: ";

cin >> x;

cout << "Левая верхняя точка - y: ";

cin >> y;

rct->SetX(x);

rct->SetY(y);

break;

}

case 6:

{

cout << "Введите длину: ";

cin >> a;

cout << "Введите ширину: ";

cin >> b;

((RectangleF*)rct)->SetA(a);

((RectangleF*)rct)->SetB(b);

break;

}

case 7:

{

cout << "Площадь прямоугольника: " << ((RectangleF*)rct)->CalcSquare() << endl;

cout << "Периметр прямоугольника: " << ((RectangleF*)rct)->CalcPerimeter() << endl;

}

case 8:

{

cout << "Введите координаты для перемещения круга\n";

cout << "Центр - x: ";

cin >> x;

cout << "Центр - y: ";

cin >> y;

crl->SetX(x);

crl->SetY(y);

break;

}

case 9:

{

cout << "Введите радиус: ";

cin >> r;

((Circle*)crl)->SetR(r);

break;

}

case 10:

{

cout << "Площадь окружности: " << ((Circle*)crl)->CalcSquare() << endl;

cout << "Периметр окружности: " << ((Circle*)crl)->CalcPerimeter() << endl;

break;

}

case 11: //запись в файл

{

ofstream out("figures.txt"); //создаем файл