Домашняя работа по курсу “Программирование на основе классов и шаблонов” 2 семестра кафедры ИУ5 МГТУ им Н.Э. Баумана.

Содержание

Цели и задачи

Освоить разработку шаблонных классов, работу с динамической памятью и применение стандартных алгоритмов STL.

Разрешено использование алгоритмов STL (std::sort, std::find, std::copy_if и др.),
но запрещено использование контейнеров STL (vector, list и т.д.).

Шаблонный класс Container<T>

Реализуйте шаблонный класс-контейнер для хранения набора объектов. Внутри должен храниться динамический массив, который автоматически расширяется при добавлении
новых элементов и может сжиматься при удалении.

Требования к классу Container:

Шаблонный класс Database<T>

Класс-обёртка над Container<T>, который добавляет логику работы с файлами и
сортировку.

Требования к классу Database:

Каждый метод Database должен вызывать соответствующий метод Container (реализация не дублируется) (например, pushBack() вызывает push() контейнера).

Классы для хранения

Вам нужно продемонстрировать работу Database с двумя типами данных:

Класс Planet

Поля:

Реализовать:

Демонстрация работы

В функции RunApplication() продумать вызов меню, где обеспечить возможность:

  1. Создать Database<Planet> и Database<MyClass>.
  2. Добавить несколько элементов вручную.
  3. Вывести содержимое.
  4. Продемонстрировать сортировку (обоими методами).
  5. Сформировать новую базу данных, скопировав элементы из существующей с помощью std::copy_if и лямбда-выражения.Для работы copyIf в классе Database надо добавить методы begin() и end(), которые возвращают итераторы на начало и конец контейнера (используют соответствующие методы класса Container).
  6. Продемонстрировать поиск элемента.
  7. Сохранить данные в файл.
  8. Очистить базу, прочитать из файла и снова вывести (проверка сохранения).

Приложение 1. Базовый класс Iterator

template <typename T>
class Container {
	<поля>
public:
	// ... остальной код контейнера


	class Iterator {
		T* ptr;
	public:
		Iterator(T* p) : ptr(p) {}

		// Разыменование
		T& operator*() const { return *ptr; }

		// Переход к следующему элементу
		Iterator& operator++() { ++ptr; return *this; }

		// Проверка на неравенство (важно для циклов и алгоритмов)
		bool operator!=(const Iterator& other) const { return ptr != other.ptr; }

		// Оператор равенства
		bool operator==(const Iterator& other) const { return ptr == other.ptr; }
	};

	// Методы для связи с STL
	Iterator begin() { return Iterator(<начало массива>); }
	Iterator end()   { return Iterator(<начало массива> + размер); }
};

Приложение 2. Требования и вопросы к дз

  1. Корректность работы с памятью — .

    • Конструкторы (по умолчанию, копирования, перемещения) работают корректно.
    • Операторы присваивания (копирующий и перемещающий) реализованы правильно.
    • Деструктор освобождает выделенную память (нет утечек).
    • Правило пяти соблюдено для Container, Database и обоих хранимых классов (Planet, MyClass).
    • При копировании/присваивании не происходит двойного удаления (double free).
  2. Реализация класса Container<T>.

    • Динамическое расширение/сжатие:
      • push() расширяет массив при переполнении.
      • deleteAt() / pop() могут уменьшать capacity (например, если count <= capacity/4 и capacity > начальной).
    • operator[] с проверкой границ.
    • operator== — поэлементное сравнение.
    • operator< — лексикографическое сравнение.
    • Методы: push(), pop(), deleteAt(), clear(), resize(), begin(), end().
    • Итератор (обязателен для поддержки STL-алгоритмов).
  3. Реализация класса Database<T> — вес .

    • Обёртка над Container:

      • pushBack() вызывает push().
      • removeAt() вызывает deleteAt().
      • removeLast() вызывает pop().
      • clear() вызывает clear().
    • Правило пяти для Database (деструктор, копирование/перемещение).

    • Работа с файлами:

      • readFromFile — чтение через оператор >>.
      • writeToFile — запись через оператор <<.
    • Сортировка:

      • Своя быстрая сортировка sortQsort(comparator)
        sortStd через std::sort.
    • find(value) — использует std::find.

    • display, inputFromConsole.

    • Методы не дублируют логику — делегируют Container.

  4. Классы Planet и ваш класс из 3-й ЛР — вес

    • Правило пяти (или хотя бы минимум: конструкторы, деструктор, операнды).
    • operator==.
    • operator< (по названию для Planet).
    • operator<< и operator>> для потокового ввода/вывода.
    • Ваш класс должен корректно храниться в Container (не нарушать инварианты при копировании).
  5. Демонстрация работы (RunApplication()) — вес .

Проверяется наглядность и полнота:

  1. Демонстрация работы с тестовым классом (тестовый класс предоставляется преподавателем) - вес 2б.

Вопросы к ДЗ

  1. В чём отличие конструктора копирования от конструктора перемещения.
  2. Зачем в Container нужен конструктор перемещения, если есть конструктор копирования? При каком сценарии он вызывается?
  3. Есть ли проверка в операторе[] на границы контейнера? Что будет, если выйти за пределы размера?
  4. В чём разница между delete и delete[]? Почему в деструкторе Container используется delete[] data, а не delete data?
  5. Как Database::find использует std::find? Что нужно реализовать в Container, чтобы std::find работал?
  6. Что произойдёт с Database<Planet>, если Planet не определяет operator==? А если не определяет operator<<?
  7. Как работает copyIf? Почему он требует, чтобы целевой контейнер имел pushBack.
  8. Что будет, если в Database::readFromFile файл не существует или в нём неправильный формат?
  9. Как Container::begin() и Container::end() позволяют использовать range-based for? Будет ли работать for (auto& item : container)?
  10. Почему метод Container::operator[] возвращает T&, а не T? Что это даёт?
  11. Объяснить алгоритм сортировки.
  12. Что такое компаратор?
  13. Что такое лямбда? Показать пример.
  14. Что такое захват лямбды?