Rückblick - Studentenverwaltungssystem
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 39 von 104.
Es ist Zeit, Ihr Wissen über Kapselung in die Praxis umzusetzen! In dieser Herausforderung werden Sie ein Student Records System (Studentenverwaltungssystem) erstellen, das die korrekte Verwendung von Zugriffsspezifizierern, Informationsverbergung (Information Hiding) und verschachtelten Klassen demonstriert.
Ihr System wird Studentendaten mit diesen Kapselungsprinzipien verwalten:
- Private Datenelemente zum Schutz sensibler Informationen wie Noten und Studenten-IDs
- Öffentliche Schnittstelle mit Gettern und kontrollierten Settern
- Eine verschachtelte Klasse zur Darstellung einzelner Kursnoten, um dieses Implementierungsdetail innerhalb der Studentenklasse zu halten
Hier ist die Struktur, die Sie implementieren werden:
class Student {
public:
class Grade { // Nested class for course grades
// ...
};
// Public interface for interacting with student data
private:
std::string name;
int studentId;
// Collection of grades
};Diese Herausforderung kombiniert alles aus diesem Kapitel: die Auswahl geeigneter Zugriffsebenen, das Verbergen von Implementierungsdetails hinter einer sauberen Schnittstelle und die Verwendung verschachtelter Klassen zur Organisation verwandter Typen. Überlegen Sie genau, was zugänglich sein sollte und was verborgen bleiben muss.
Aufgabe
EinfachLassen Sie uns ein Student-Records-System erstellen, das alles zusammenführt, was Sie über Kapselung gelernt haben. Sie werden ein System erstellen, in dem Studentendaten ordnungsgemäß geschützt sind, Noten über eine verschachtelte Klasse verwaltet werden und alle Interaktionen über eine saubere öffentliche Schnittstelle erfolgen.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
Student.h: Definieren Sie eineStudent-Klasse, die eine ordnungsgemäße Kapselung mit einer verschachteltenGrade-Klasse demonstriert.Ihre verschachtelte
Grade-Klasse (deklariert im öffentlichen Bereich vonStudent) sollte einen Kursnamen (string) und eine Punktzahl (double) speichern. Geben Sie ihr einen Konstruktor, der beide Werte entgegennimmt, und stellen Sie die MethodengetCourseName()undgetScore()bereit, um auf die Daten zuzugreifen. DieGrade-Klasse hält ihre Daten privat — obwohl sie innerhalb vonStudentverschachtelt ist, behält sie dennoch ihre eigene Kapselung bei.Die
Student-Klasse sollte private Member für den Namen des Studenten (string), die Studenten-ID (int) und eine Sammlung vonGrade-Pointern haben. Stellen Sie Folgendes bereit:- Einen Konstruktor, der den Namen und die Studenten-ID entgegennimmt
- Getter
getName()undgetStudentId()(beide const) - Eine Methode
addGrade(const std::string& course, double score), die eine neueGradeerstellt und sie dem Datensatz des Studenten hinzufügt (nur hinzufügen, wenn die Punktzahl zwischen 0 und 100 einschließlich liegt) - Eine Methode
getAverageGrade()(const), die den Durchschnitt aller Noten berechnet und zurückgibt, oder 0.0, falls keine Noten vorhanden sind - Eine Methode
displayRecord()(const), die den vollständigen Datensatz des Studenten anzeigt
Vergessen Sie nicht, dynamisch zugewiesene Noten im Destruktor zu bereinigen, und fügen Sie ordnungsgemäße Header-Guards ein.
main.cpp: Lesen Sie einen Studentennamen, eine Studenten-ID und drei Kursnoten aus der Eingabe ein. Das Eingabeformat besteht aus fünf Zeilen: Name, ID, dann drei Zeilen, die jeweils einen Kursnamen und eine Punktzahl enthalten, getrennt durch ein Leerzeichen (z. B.Math 95.5).Erstellen Sie einen
Studentmit dem Namen und der ID, fügen Sie alle drei Noten hinzu und zeigen Sie dann den vollständigen Datensatz an.Das Ausgabeformat für
displayRecord()sollte wie folgt aussehen:Student: <name> (ID: <id>) Grades: <course1>: <score1> <course2>: <score2> <course3>: <score3> Average: <average>
Formatieren Sie alle Punktzahlen und den Durchschnitt mit einer Dezimalstelle unter Verwendung von std::fixed und std::setprecision(1) aus <iomanip>. Konvertieren Sie die ID mit std::stoi() und die Punktzahlen mit std::stod().
Diese Herausforderung kombiniert private Datenelemente, öffentliche Getter, kontrollierte Setter mit Validierung und eine verschachtelte Klasse — alles arbeitet zusammen, um ein gut gekapseltes Student-Records-System zu erstellen.
Spickzettel
Kapselung kombiniert Zugriffsspezifizierer, Informationsverbergung und verschachtelte Klassen, um Daten zu schützen und Code zu organisieren.
Zugriffsspezifizierer für den Datenschutz
Verwenden Sie private für sensible Datenelemente und public für die Schnittstelle:
class Student {
public:
// Öffentliche Schnittstellenmethoden
private:
std::string name;
int studentId;
// Andere private Daten
};Verschachtelte Klassen
Verschachtelte Klassen organisieren verwandte Typen innerhalb einer Klasse und behalten ihre eigene Kapselung bei:
class Student {
public:
class Grade { // Verschachtelte Klasse
private:
std::string courseName;
double score;
public:
Grade(const std::string& course, double s)
: courseName(course), score(s) {}
std::string getCourseName() const { return courseName; }
double getScore() const { return score; }
};
private:
std::vector<Grade*> grades;
};Kontrollierter Zugriff mit Validierung
Methoden können Daten validieren, bevor sie private Member ändern:
void addGrade(const std::string& course, double score) {
if (score >= 0 && score <= 100) {
grades.push_back(new Grade(course, score));
}
}Const-Methoden
Markieren Sie Methoden, die keine Daten ändern, als const:
std::string getName() const { return name; }
double getAverageGrade() const {
// Durchschnitt berechnen und zurückgeben
}Speicherverwaltung
Bereinigen Sie dynamisch zugewiesene Objekte im Destruktor:
~Student() {
for (Grade* grade : grades) {
delete grade;
}
}Probier es selbst
#include <iostream>
#include <string>
#include <sstream>
#include "Student.h"
int main() {
// Studentennamen lesen
std::string name;
std::getline(std::cin, name);
// Studenten-ID lesen
std::string idStr;
std::getline(std::cin, idStr);
int studentId = std::stoi(idStr);
// Drei Kursnoten lesen (Format: "CourseName Score")
std::string line1, line2, line3;
std::getline(std::cin, line1);
std::getline(std::cin, line2);
std::getline(std::cin, line3);
// TODO: Jede Zeile parsen, um Kursnamen und Punktzahl zu extrahieren
// std::stod() verwenden, um Punktzahl-Strings in doubles umzuwandeln
// TODO: Ein Student-Objekt mit dem Namen und der ID erstellen
// TODO: Alle drei Noten zum Studenten hinzufügen
// TODO: Den vollständigen Datensatz des Studenten anzeigen
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamensräume & GültigkeitsbereicheEinführung in OOP in C++Klassen vs. ObjekteDer 'this'-PointerMethoden (Elementfunktionen)Attribute (Datenelemente)Grundlagen zu Ctors & DtorsRückblick - Einfacher Taschenrechner4Klasseneigenschaften
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen & KlassenZusammenfassung - Bankkonto-Manager7Vererbung
Grundlagen der VererbungZugriffsstufen bei VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick - Mitarbeiter-Hierarchie2Speicherverwaltung
Stack vs. Heap SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Smart Pointers in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsspezifizierer in C++Zugriffsspezifizierer im DetailInformation HidingStruct vs. ClassVerschachtelte & innere KlassenRückblick - Studentenverwaltungssystem8Polymorphie
Kompilierzeit- vs. Laufzeit-PolymorphieFunktionsüberladungVirtuelle Funktionen – WiederholungRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIZusammenfassung – Formen-Rechner3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorVerschiebekonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktoren im DetailRule of Three / Five / ZeroZusammenfassung - String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladen der [] und () OperatorenTypumwandlungsoperatorenRückblick - Matrix-Klasse9Templates
FunktionstemplatesKlassentemplatesTemplate-SpezialisierungVariadische TemplatesSFINAE & Type Traits GrundlagenRückblick - Generische Container