Министерство образования Республики Беларусь
Министерство образования Республики Беларусь
БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ
Кафедра эконмической информатики
Объектно-ориентированное программирование
“Классы и объекты в языке C++”
Выполнила: Студентка группы
972303
Рушева Маргарита
Владиславовна
Проверила: Григорьева Юлия
Юрьевна
Минск, 2020
Изучить структуру класса, атрибуты доступа к компонентам класса; рассмотреть принцип работы конструкторов (с параметрами, без параметров, с параметрами по умолчанию, конструктора копирования), деструкторов при работе с объектом, статические и константные данные и методы класса.
КЛАСС в объектно-ориентированном программировании, представляет собой шаблон для создания объектов, обеспечивающий начальные значения состояний: инициализация полей-переменных и реализация поведения функций или методов. Объявление класса начинается с ключевого слова 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.1 – Индивидуальное задание
“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"); //создаем файл