Платформа для онлайн-обучения
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 103 из 104.
Задание
ЛегкоДавайте создадим платформу электронного обучения (E-Learning Platform), которая объединит все концепции ООП, освоенные вами в этом курсе. Вы создадите систему, которая управляет курсами, различными типами уроков и отслеживает прогресс студентов, демонстрируя иерархии наследования, полиморфизм, умные указатели и паттерны проектирования, работающие в гармонии.
Вы распределите свой код по шести файлам:
User.h: Создайте иерархию пользователей с базовым классомUserи двумя производными классами:StudentиInstructor.Ваш базовый класс
Userдолжен иметь имя и ID, виртуальный методgetRole(), который возвращает тип пользователя в виде строки, и методgetInfo(), который возвращает"[name] ([id]) - [role]".Класс
Studentотслеживает ID курсов, на которые он записан (используйте вектор строк), и количество пройденных уроков. Добавьте методыenrollInCourse(const std::string& courseId),completedLesson()для увеличения счетчика иgetCompletedCount().Класс
Instructorхранит строку со специализацией и отслеживает ID курсов, которые он ведет. ДобавьтеaddCourse(const std::string& courseId)иgetSpecialty().Lesson.h: Постройте иерархию уроков, используя абстрактный базовый класс.Ваш базовый класс
Lessonдолжен иметь название и продолжительность (в минутах), чисто виртуальный методcomplete(), который возвращает сообщение о завершении, и методgetType(), возвращающий тип урока.Создайте три производных класса:
VideoLesson: Имеет URL-адрес видео. Его методcomplete()возвращает"Watched video: [title]"QuizLesson: Имеет количество вопросов. Его методcomplete()возвращает"Completed quiz: [title] ([questions] questions)"TextLesson: Имеет количество слов. Его методcomplete()возвращает"Read article: [title]"
Каждый класс должен переопределять
getType(), чтобы возвращать"Video","Quiz"или"Text"соответственно.Course.h: Создайте классCourse, который владеет своими уроками с помощью умных указателей.Курс имеет название, ID и ID инструктора. Храните уроки как
std::vector<std::unique_ptr<Lesson>>, так как курс владеет своими уроками эксклюзивно.Добавьте методы:
addLesson(std::unique_ptr<Lesson> lesson)— передает владение уроком курсуgetLessonCount()— возвращает количество уроковgetLesson(size_t index)— возвращает указатель на урок по этому индексу (или nullptr, если индекс невалиден)displayCurriculum()— выводит тип и название каждого урока в формате"[index]. [Type]: [title]"
LessonFactory.h: Реализуйте паттерн «Фабрика» для создания различных типов уроков.Создайте класс
LessonFactoryсо статическим методомcreateLesson(const std::string& type, const std::string& title, int duration, const std::string& extra), который возвращаетstd::unique_ptr<Lesson>.Параметр
typeопределяет, какой урок создать ("video","quiz"или"text"). Параметрextraсодержит данные, специфичные для типа: URL для видео, количество вопросов для теста (преобразовать в int) или количество слов для текста (преобразовать в int).Platform.h: Создайте центральный классPlatform, который координирует всё остальное.Храните курсы как
std::vector<std::shared_ptr<Course>>, а пользователей какstd::vector<std::shared_ptr<User>>.Реализуйте:
addCourse(std::shared_ptr<Course> course)addUser(std::shared_ptr<User> user)findCourse(const std::string& id)— возвращает shared_ptr или nullptrfindUser(const std::string& id)— возвращает shared_ptr или nullptrenrollStudent(const std::string& studentId, const std::string& courseId)— находит обоих, записывает студента, выводит"Enrolled [name] in [course title]"или"Enrollment failed"completeLesson(const std::string& studentId, const std::string& courseId, size_t lessonIndex)— находит студента и курс, вызывает метод complete() урока, увеличивает счетчик пройденных уроков студента, выводит сообщение о завершении или"Could not complete lesson"
main.cpp: Соберите всё вместе, чтобы продемонстрировать работу вашей платформы.Прочитайте четыре входных значения:
- Название платформы
- Детали курса (формат:
title,courseId,instructorId) - Детали студента (формат:
name,studentId) - Урок для добавления (формат:
type,title,duration,extra)
Создайте платформу и выведите
"Welcome to [platform name]!". Создайте курс и студента, добавьте их на платформу. Используйте LessonFactory для создания урока и добавьте его в курс. Выведите учебный план курса. Запишите студента на курс. Завершите первый урок (индекс 0) для этого студента. Наконец, выведите информацию о студенте и количество пройденных им уроков в формате"Completed lessons: [count]".
Например, при входных данных CodeAcademy, C++ Mastery,CPP101,I001, Alice,S001 и video,Introduction to OOP,30,https://example.com/oop:
Welcome to CodeAcademy!
1. Video: Introduction to OOP
Enrolled Alice in C++ Mastery
Watched video: Introduction to OOP
Alice (S001) - Student
Completed lessons: 1При входных данных LearnHub, Python Basics,PY100,I002, Bob,S002 и quiz,Variables Quiz,15,10:
Welcome to LearnHub!
1. Quiz: Variables Quiz
Enrolled Bob in Python Basics
Completed quiz: Variables Quiz (10 questions)
Bob (S002) - Student
Completed lessons: 1Эта задача демонстрирует структуру реальных платформ электронного обучения — с четким разделением между пользователями, контентом и платформой, которая их координирует. Паттерн «Фабрика» делает создание уроков гибким, умные указатели обеспечивают безопасное управление памятью, а полиморфизм позволяет единообразно работать со всеми типами уроков, в то время как каждый из них ведет себя уникально.
Попробуйте сами
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "User.h"
#include "Lesson.h"
#include "Course.h"
#include "LessonFactory.h"
#include "Platform.h"
int main() {
// Чтение входных данных
std::string platformName;
std::getline(std::cin, platformName);
std::string courseDetails; // формат: title,courseId,instructorId
std::getline(std::cin, courseDetails);
std::string studentDetails; // формат: name,studentId
std::getline(std::cin, studentDetails);
std::string lessonDetails; // формат: type,title,duration,extra
std::getline(std::cin, lessonDetails);
// TODO: Разобрать courseDetails, чтобы извлечь title, courseId, instructorId
// TODO: Разобрать studentDetails, чтобы извлечь name, studentId
// TODO: Разобрать lessonDetails, чтобы извлечь type, title, duration, extra
// TODO: Создать платформу и вывести "Welcome to [platform name]!"
// TODO: Создать курс и студента, добавить их на платформу
// TODO: Использовать LessonFactory для создания урока и добавить его в курс
// TODO: Отобразить учебную программу курса
// TODO: Записать студента на курс
// TODO: Завершить первый урок (индекс 0) для студента
// TODO: Вывести информацию о студенте и количество завершенных уроков
// Формат: "Completed lessons: [count]"
return 0;
}
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнер