Resumen - Sistema de registros de estudiantes
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 39 de 104.
¡Es hora de poner en práctica tus conocimientos sobre encapsulación! En este desafío, construirás un Sistema de Registros de Estudiantes que demuestre el uso adecuado de los especificadores de acceso, la ocultación de información y las clases anidadas.
Tu sistema gestionará los datos de los estudiantes con estos principios de encapsulación:
- Miembros de datos privados para proteger información sensible como calificaciones e IDs de estudiantes
- Interfaz pública con getters y setters controlados
- Una clase anidada para representar las calificaciones de cursos individuales, manteniendo este detalle de implementación contenido dentro de la clase de estudiante
Aquí está la estructura que implementarás:
class Student {
public:
class Grade { // Clase anidada para calificaciones de cursos
// ...
};
// Interfaz pública para interactuar con los datos del estudiante
private:
std::string name;
int studentId;
// Colección de calificaciones
};Este desafío combina todo lo de este capítulo: elegir los niveles de acceso adecuados, ocultar los detalles de implementación detrás de una interfaz limpia y usar clases anidadas para organizar tipos relacionados. Piensa detenidamente en qué debería ser accesible y qué debería permanecer oculto.
Desafío
FácilVamos a construir un Sistema de Registros de Estudiantes que reúna todo lo que has aprendido sobre el encapsulamiento. Crearás un sistema donde los datos de los estudiantes estén debidamente protegidos, las calificaciones se gestionen a través de una clase anidada y todas las interacciones ocurran a través de una interfaz pública limpia.
Crearás dos archivos para organizar tu código:
Student.h: Define una claseStudentque demuestre un encapsulamiento adecuado con una clase anidadaGrade.Tu clase anidada
Grade(declarada en la sección pública deStudent) debe almacenar un nombre de curso (string) y una puntuación (double). Dale un constructor que reciba ambos valores y proporciona los métodosgetCourseName()ygetScore()para acceder a los datos. La claseGrademantiene sus datos privados; aunque esté anidada dentro deStudent, sigue manteniendo su propio encapsulamiento.La clase
Studentdebe tener miembros privados para el nombre del estudiante (string), el ID del estudiante (int) y una colección de punterosGrade. Proporciona:- Un constructor que reciba el nombre y el ID del estudiante
- Getters
getName()ygetStudentId()(ambos const) - Un método
addGrade(const std::string& course, double score)que cree un nuevoGradey lo añada al registro del estudiante (solo añadir si la puntuación está entre 0 y 100 inclusive) - Un método
getAverageGrade()(const) que calcule y devuelva el promedio de todas las calificaciones, o 0.0 si no existen calificaciones - Un método
displayRecord()(const) que muestre el registro completo del estudiante
No olvides limpiar las calificaciones asignadas dinámicamente en el destructor e incluir los protectores de encabezado (header guards) adecuados.
main.cpp: Lee un nombre de estudiante, un ID de estudiante y tres calificaciones de cursos de la entrada. El formato de entrada será de cinco líneas: nombre, ID, y luego tres líneas, cada una con el nombre de un curso y una puntuación separados por un espacio (por ejemplo,Math 95.5).Crea un
Studentcon el nombre e ID, añade las tres calificaciones y luego muestra el registro completo.El formato de salida para
displayRecord()debe ser:Student: <name> (ID: <id>) Grades: <course1>: <score1> <course2>: <score2> <course3>: <score3> Average: <average>
Formatea todas las puntuaciones y el promedio con un decimal usando std::fixed y std::setprecision(1) de <iomanip>. Convierte el ID usando std::stoi() y las puntuaciones usando std::stod().
Este desafío combina miembros de datos privados, getters públicos, setters controlados con validación y una clase anidada, todo trabajando en conjunto para crear un sistema de registros de estudiantes bien encapsulado.
Hoja de referencia
La encapsulación combina especificadores de acceso, ocultación de información y clases anidadas para proteger los datos y organizar el código.
Especificadores de acceso para la protección de datos
Use private para los miembros de datos sensibles y public para la interfaz:
class Student {
public:
// Métodos de interfaz pública
private:
std::string name;
int studentId;
// Otros datos privados
};Clases anidadas
Las clases anidadas organizan tipos relacionados dentro de una clase, manteniendo su propia encapsulación:
class Student {
public:
class Grade { // Clase anidada
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;
};Acceso controlado con validación
Los métodos pueden validar los datos antes de modificar los miembros privados:
void addGrade(const std::string& course, double score) {
if (score >= 0 && score <= 100) {
grades.push_back(new Grade(course, score));
}
}Métodos Const
Marque los métodos que no modifican los datos como const:
std::string getName() const { return name; }
double getAverageGrade() const {
// Calcular y devolver el promedio
}Gestión de memoria
Limpie los objetos asignados dinámicamente en el destructor:
~Student() {
for (Grade* grade : grades) {
delete grade;
}
}Pruébalo tú mismo
#include <iostream>
#include <string>
#include <sstream>
#include "Student.h"
int main() {
// Leer el nombre del estudiante
std::string name;
std::getline(std::cin, name);
// Leer el ID del estudiante
std::string idStr;
std::getline(std::cin, idStr);
int studentId = std::stoi(idStr);
// Leer tres calificaciones de cursos (formato: "CourseName Score")
std::string line1, line2, line3;
std::getline(std::cin, line1);
std::getline(std::cin, line2);
std::getline(std::cin, line3);
// TODO: Analizar cada línea para extraer el nombre del curso y la puntuación
// Usar std::stod() para convertir las cadenas de puntuación a doubles
// TODO: Crear un objeto Student con el nombre y el ID
// TODO: Añadir las tres calificaciones al estudiante
// TODO: Mostrar el registro completo del estudiante
return 0;
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genérico