Перейти к основному содержимому

О декомпозиции проекта при работе с множествами объектов

· 3 мин. чтения
Дмитрий Аладин
Преподаватель

На данном семинаре обсуждались возникшие вопросы о лабораторной работе №2 и рассматривались способы декомпозиции проекта при работе с множествами объектов.

Декомпозиция проекта при работе с множествами объектов

Исходная задача

Исходная задача и первый подход к декомпозиции представлен в примере для лабораторной работы №2.

Подход 2: хранение множества объектов в классе-агрегат

Объектно-ориентированный подход, как упоминается в лекции "Концепции и парадигмы программирования", принес в мир программирования множество подходов к декомпозиции программ, проектов, систем. Давайте воспользуемся одним из подходов и к нашей задаче.

Давайте переложим ответственность за хранение нашего множества объектов на класс-агрегат.

Агрегат или аггрегат (лат. aggregatus — соединённый, собранный) — нечто составное, совокупность элементов, образующих систему или её часть.

Один из вариантов реализации класса-агрегата Rectangles выглядит следующим образом:

#include <iostream>

class Rectangle {
private:
int a_, b_;
public:
Rectangle() {}

Rectangle(int a, int b) {
this->a_ = a;
this->b_ = b;
}

Rectangle(const Rectangle &rec) {
this->a_ = rec.a_;
this->b_ = rec.b_;
}

int getA() {
return a_;
}

int getB() {
return b_;
}

void setA(int a) {
this->a_ = a;
}

void setB(int b) {
this->b_ = b;
}

void set(int a, int b) {
setA(a);
setB(b);
}

Rectangle &operator=(const Rectangle &right) {
if (this == &right) {
return *this;
}
setA(right.a_);
setB(right.b_);
return *this;
}
};

class Rectangles {
Rectangle *arr_;
int n_;
private:
void resize(int n) {
if (n_ == 0) {
this->arr_ = new Rectangle[n];
this->n_ = n;
return;
}
this->n_ = n;
this->arr_ = static_cast<Rectangle *>(realloc(this->arr_, sizeof(Rectangle) * n));
}

public:
Rectangles() {}

~Rectangles() {
if (arr_ != nullptr) {
delete[] this->arr_;
}
}

void add(const Rectangle *rec) {
resize(this->n_ + 1);
this->arr_[n_ - 1] = *rec;
}

void showRectangles() {
for (int i = 0; i < this->n_; i++) {
std::cout << "I know about the rectangle # " << i
<< ". It has: " << std::endl;
std::cout << " a=" << this->arr_[i].getA() << std::endl;
std::cout << " b=" << this->arr_[i].getB() << std::endl;
}
}

int calculateAreas() {
int sum = 0;
for (int i = 0; i < this->n_; i++) {
sum += this->arr_[i].getA() * this->arr_[i].getB();
}
return sum;
}
};

int main() {
Rectangles *recs = new Rectangles();
Rectangle *rec1 = new Rectangle(1, 3);
Rectangle *rec2 = new Rectangle(4, 6);
recs->add(rec1);
recs->add(rec2);

recs->showRectangles();
std::cout << std::endl;
std::cout << "Sum of the areas of all rectangles: "
<< recs->calculateAreas() << std::endl;
delete recs;
delete rec1;
delete rec2;
}

Обратите внимание на то, что:

  1. В примере показывается:
    1. Реализация расширения динамического массива.
    2. Реализация конструктора копирования и перегрузка оператора =.
  2. Необходимо реализовать деконструктор класса, если в объекте используется выделенная вручную память.
  3. Если объект создан с помощью операции new, то для его уничтожения применяется операция delete.

В результате мы получаем элегантное решение и распределение ответственности между составляющими проекта, используя принципы ООП.

Дополнительная информация

В оставшееся свободное время предлагается обсудить следующие вопросы:

  1. Использование консольных команд:
    1. Полезные консольные команды для Linux