Итоги — Система учета студентов
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 39 из 104.
Пора применить на практике свои знания об инкапсуляции! В этом задании ты создашь систему учёта студентов, демонстрирующую правильное использование спецификаторов доступа, сокрытие информации и вложенных классов.
Твоя система будет управлять данными студентов, используя следующие принципы инкапсуляции:
- Закрытые члены данных для защиты конфиденциальной информации, такой как оценки и идентификаторы студентов
- Открытый интерфейс с геттерами и управляемыми сеттерами
- Вложенный класс для представления оценок за отдельные курсы, чтобы эта деталь реализации оставалась внутри класса студента
Вот структура, которую тебе предстоит реализовать:
class Student {
public:
class Grade { // Вложенный класс для оценок по курсам
// ...
};
// Публичный интерфейс для взаимодействия с данными студента
private:
std::string name;
int studentId;
// Коллекция оценок
};В этом задании объединены все темы из этой главы: выбор подходящих уровней доступа, сокрытие деталей реализации за чистым интерфейсом и использование вложенных классов для организации связанных типов. Внимательно подумай, что должно быть доступно, а что следует оставить скрытым.
Задание
ЛегкоСоздадим систему учёта студентов, которая объединит всё, что вы узнали об инкапсуляции. Вы создадите систему, в которой данные студентов надёжно защищены, оценки управляются через вложенный класс, а все взаимодействия происходят через чистый публичный интерфейс.
Вы создадите два файла, чтобы организовать свой код:
Student.h: определитеStudentкласс, демонстрирующий правильную инкапсуляцию с вложеннымGradeклассом.Ваш вложенный
Gradeкласс (объявленный в публичной секцииStudent) должен хранить название курса (строка) и оценку (число типа double). Добавьте конструктор, принимающий оба значения, а также методыgetCourseName()иgetScore()для доступа к данным.Gradeкласс хранит свои данные в закрытой области: несмотря на то, что он вложен вStudent, он по-прежнему сохраняет собственную инкапсуляцию.Studentкласс должен иметь закрытые члены для имени студента (строка), идентификатора студента (целое число) и collection указателей наGrade. Добавьте:- Конструктор, принимающий имя и идентификатор студента
- Геттеры
getName()иgetStudentId()(оба const) - Метод
addGrade(const std::string& course, double score), который создаёт новыйGradeи добавляет его в запись студента (добавлять только если score находится в диапазоне от 0 до 100 включительно) - Метод
getAverageGrade()(const), который вычисляет и возвращает среднее значение всех оценок или 0.0, если оценок не существует - Метод
displayRecord()(const), который отображает полную запись студента
Не забудьте освободить dynamically выделенные оценки в деструкторе и добавить правильные include guards.
main.cpp: считайте из входных данных имя студента, идентификатор студента и оценки по трём курсам. Формат входных данных — пять строк: имя, ID, затем три строки, каждая из которых содержит название курса и оценку, разделённые пробелом (например,Math 95.5).Создайте
Studentс именем и ID, добавьте все три оценки, затем отобразите полную запись.Формат вывода для
displayRecord()должен быть следующим:Student: <name> (ID: <id>) Grades: <course1>: <score1> <course2>: <score2> <course3>: <score3> Average: <average>
Отформатируйте все оценки и среднее значение с одним знаком после десятичной точки, используя std::fixed и std::setprecision(1) из <iomanip>. Преобразуйте ID с помощью std::stoi(), а оценки — с помощью std::stod().
Это задание объединяет закрытые члены данных, публичные геттеры, управляемые сеттеры с проверкой и вложенный класс: всё это работает вместе для создания хорошо инкапсулированной системы учёта студентов.
Попробуйте сами
#include <iostream>
#include <string>
#include <sstream>
#include "Student.h"
int main() {
// Считать имя студента
std::string name;
std::getline(std::cin, name);
// Считать ID студента
std::string idStr;
std::getline(std::cin, idStr);
int studentId = std::stoi(idStr);
// Считать три оценки по курсам (формат: "CourseName Score")
std::string line1, line2, line3;
std::getline(std::cin, line1);
std::getline(std::cin, line2);
std::getline(std::cin, line3);
// TODO: Разобрать каждую строку, чтобы извлечь название курса и оценку
// Использовать std::stod() для преобразования строк оценок в doubles
// TODO: Создать объект Student с именем и ID
// TODO: Добавить все три оценки студенту
// TODO: Отобразить полную запись студента
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Итоги — Обобщенный контейнерПотренируйтесь самостоятельно: Онлайн-компилятор C++