Recap - Student Records System
Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 39 of 104.
Time to put your encapsulation knowledge into practice! In this challenge, you'll build a Student Records System that demonstrates proper use of access specifiers, information hiding, and nested classes.
Your system will manage student data with these encapsulation principles:
- Private data members to protect sensitive information like grades and student IDs
- Public interface with getters and controlled setters
- A nested class to represent individual course grades, keeping this implementation detail contained within the student class
Here's the structure you'll implement:
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
};This challenge combines everything from this chapter: choosing appropriate access levels, hiding implementation details behind a clean interface, and using nested classes to organize related types. Think carefully about what should be accessible and what should remain hidden.
Challenge
EasyLet's build a Student Records System that brings together everything you've learned about encapsulation. You'll create a system where student data is properly protected, grades are managed through a nested class, and all interactions happen through a clean public interface.
You'll create two files to organize your code:
Student.h: Define aStudentclass that demonstrates proper encapsulation with a nestedGradeclass.Your nested
Gradeclass (declared in the public section ofStudent) should store a course name (string) and a score (double). Give it a constructor that takes both values, and providegetCourseName()andgetScore()methods to access the data. TheGradeclass keeps its data private — even though it's nested insideStudent, it still maintains its own encapsulation.The
Studentclass should have private members for the student's name (string), student ID (int), and a collection ofGradepointers. Provide:- A constructor that takes the name and student ID
- Getters
getName()andgetStudentId()(both const) - A method
addGrade(const std::string& course, double score)that creates a newGradeand adds it to the student's record (only add if score is between 0 and 100 inclusive) - A method
getAverageGrade()(const) that calculates and returns the average of all grades, or 0.0 if no grades exist - A method
displayRecord()(const) that shows the student's complete record
Don't forget to clean up dynamically allocated grades in the destructor, and include proper header guards.
main.cpp: Read a student name, student ID, and three course grades from input. The input format will be five lines: name, ID, then three lines each containing a course name and score separated by a space (e.g.,Math 95.5).Create a
Studentwith the name and ID, add all three grades, then display the complete record.The output format for
displayRecord()should be:Student: <name> (ID: <id>) Grades: <course1>: <score1> <course2>: <score2> <course3>: <score3> Average: <average>
Format all scores and the average with one decimal place using std::fixed and std::setprecision(1) from <iomanip>. Convert the ID using std::stoi() and scores using std::stod().
This challenge combines private data members, public getters, controlled setters with validation, and a nested class — all working together to create a well-encapsulated student records system.
Cheat sheet
Encapsulation combines access specifiers, information hiding, and nested classes to protect data and organize code.
Access Specifiers for Data Protection
Use private for sensitive data members and public for the interface:
class Student {
public:
// Public interface methods
private:
std::string name;
int studentId;
// Other private data
};Nested Classes
Nested classes organize related types within a class, maintaining their own encapsulation:
class Student {
public:
class Grade { // Nested class
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;
};Controlled Access with Validation
Methods can validate data before modifying private members:
void addGrade(const std::string& course, double score) {
if (score >= 0 && score <= 100) {
grades.push_back(new Grade(course, score));
}
}Const Methods
Mark methods that don't modify data as const:
std::string getName() const { return name; }
double getAverageGrade() const {
// Calculate and return average
}Memory Management
Clean up dynamically allocated objects in the destructor:
~Student() {
for (Grade* grade : grades) {
delete grade;
}
}Try it yourself
#include <iostream>
#include <string>
#include <sstream>
#include "Student.h"
int main() {
// Read student name
std::string name;
std::getline(std::cin, name);
// Read student ID
std::string idStr;
std::getline(std::cin, idStr);
int studentId = std::stoi(idStr);
// Read three course grades (format: "CourseName Score")
std::string line1, line2, line3;
std::getline(std::cin, line1);
std::getline(std::cin, line2);
std::getline(std::cin, line3);
// TODO: Parse each line to extract course name and score
// Use std::stod() to convert score strings to doubles
// TODO: Create a Student object with the name and ID
// TODO: Add all three grades to the student
// TODO: Display the complete student record
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesC++ Build & CompilationHeader Files & Source FilesNamespaces & ScopeIntroduction to OOP in C++Classes vs ObjectsThe 'this' PointerMethods (Member Functions)Attributes (Data Members)Ctors & Dtors BasicsRecap - Simple Calculator4Class Properties
Instance vs Static MembersGetters and SettersConst Member FunctionsMutable KeywordStatic Methods and VariablesFriend Functions & ClassesRecap - Bank Account Manager7Inheritance
Basic InheritanceInheritance Access LevelsCtor & Dtor Call OrderMethod OverridingVirtual Functions & VTableMultiple InheritanceVirtual InheritanceRecap - Employee Hierarchy2Memory Management
Stack vs Heap MemoryPointers and ReferencesDynamic Memory (new/delete)Smart Pointers in C++RAII in C++Recap - Dynamic Array Manager5Encapsulation
Access Specifiers in C++Access Specifiers In DepthInformation HidingStruct vs ClassNested & Inner ClassesRecap - Student Records System8Polymorphism
Compile vs Runtime PolymorphFunction OverloadingVirtual Functions RevisitedPure Virtual FunctionsAbstract ClassesInterface Design in C++Dynamic Casting & RTTIRecap - Shape Calculator3Constructors & Destructors
Default ConstructorParameterized ConstructorCopy ConstructorMove ConstructorConstructor Init ListsDelegating ConstructorsDestructor Deep DiveRule of Three / Five / ZeroRecap - String Class6Operator Overloading
Intro to Operator OverloadArithmetic Operator OverloadComparison Operator OverloadStream OperatorsAssignment Operator Overload[] and () Operator OverloadType Conversion OperatorsRecap - Matrix Class9Templates
Function TemplatesClass TemplatesTemplate SpecializationVariadic TemplatesSFINAE & Type Traits BasicsRecap - Generic Container