Ôn tập: hệ thống hồ sơ sinh viên
Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 39 trên 104.
Đã đến lúc vận dụng kiến thức về tính đóng gói! Trong thử thách này, bạn sẽ xây dựng một Hệ thống hồ sơ sinh viên để minh họa cách sử dụng đúng các chỉ định truy cập, che giấu thông tin và lớp lồng nhau.
Hệ thống của bạn sẽ quản lý dữ liệu sinh viên theo các nguyên tắc đóng gói sau:
- Các thành viên dữ liệu riêng tư để bảo vệ thông tin nhạy cảm như điểm số và mã sinh viên
- Giao diện công khai với các phương thức getter và setter có kiểm soát
- Một lớp lồng nhau để biểu diễn điểm số của từng khóa học, giữ chi tiết triển khai này bên trong lớp sinh viên
Đây là cấu trúc bạn sẽ triển khai:
class Student {
public:
class Grade { // Lớp lồng nhau lưu điểm các khóa học
// ...
};
// Giao diện công khai để tương tác với dữ liệu học sinh
private:
std::string name;
int studentId;
// Tập hợp điểm
};Thử thách này kết hợp mọi thứ trong chương này: chọn mức truy cập phù hợp, ẩn chi tiết triển khai sau một giao diện rõ ràng và dùng lớp lồng nhau để sắp xếp các kiểu liên quan. Hãy suy nghĩ kỹ xem thành phần nào nên được phép truy cập và thành phần nào cần được giữ kín.
Thử thách
DễHãy xây dựng hệ thống quản lý hồ sơ sinh viên để kết hợp mọi thứ bạn đã học về tính đóng gói. Bạn sẽ tạo một hệ thống bảo vệ dữ liệu sinh viên đúng cách, quản lý điểm thông qua một lớp lồng nhau và xử lý mọi tương tác qua một giao diện công khai gọn gàng.
Bạn sẽ tạo hai tệp để sắp xếp code:
Student.h: Định nghĩa lớpStudentđể minh họa cách đóng gói đúng cách với lớpGradelồng nhau.Lớp
Gradelồng nhau (được khai báo trong phần public củaStudent) cần lưu tên khóa học (chuỗi) và điểm (double). Tạo hàm khởi tạo nhận cả hai giá trị, đồng thời cung cấp các phương thứcgetCourseName()vàgetScore()để truy cập dữ liệu. LớpGradegiữ dữ liệu ở chế độ riêng tư. Dù được lồng trongStudent, lớp này vẫn giữ tính đóng gói riêng.Lớp
Studentcần có các thành viên riêng tư để lưu tên sinh viên (chuỗi), mã sinh viên (int) và một tập hợp con trỏGrade. Hãy cung cấp:- Hàm khởi tạo nhận tên và mã sinh viên
- Các hàm getter
getName()vàgetStudentId()(đều có từ khóa const) - Phương thức
addGrade(const std::string& course, double score)tạo mộtGrademới và thêm vào hồ sơ sinh viên (chỉ thêm nếu điểm nằm trong khoảng từ 0 đến 100, bao gồm cả hai giá trị này) - Phương thức
getAverageGrade()(có từ khóa const) tính và trả về điểm trung bình của tất cả các điểm, hoặc 0.0 nếu không có điểm nào - Phương thức
displayRecord()(có từ khóa const) hiển thị hồ sơ đầy đủ của sinh viên
Đừng quên giải phóng bộ nhớ của các điểm được cấp phát động trong hàm hủy và thêm các chỉ thị bảo vệ tiêu đề phù hợp.
main.cpp: Đọc tên sinh viên, mã sinh viên và điểm của ba khóa học từ đầu vào. Dữ liệu đầu vào gồm năm dòng: tên, mã, sau đó là ba dòng, mỗi dòng chứa tên khóa học và điểm được phân tách bằng dấu cách (ví dụ:Math 95.5).Tạo một đối tượng
Studentvới tên và mã sinh viên, thêm cả ba điểm, rồi hiển thị hồ sơ đầy đủ.Định dạng đầu ra của
displayRecord()như sau:Student: <name> (ID: <id>) Grades: <course1>: <score1> <course2>: <score2> <course3>: <score3> Average: <average>
Định dạng tất cả điểm số và điểm trung bình với một chữ số thập phân bằng std::fixed và std::setprecision(1) từ <iomanip>. Chuyển mã sinh viên bằng std::stoi() và chuyển điểm bằng std::stod().
Thử thách này kết hợp các thành viên dữ liệu riêng tư, hàm getter công khai, hàm setter có kiểm tra hợp lệ và lớp lồng nhau: tất cả phối hợp để tạo nên một hệ thống quản lý hồ sơ sinh viên được đóng gói tốt.
Tự làm thử
#include <iostream>
#include <string>
#include <sstream>
#include "Student.h"
int main() {
// Đọc tên sinh viên
std::string name;
std::getline(std::cin, name);
// Đọc mã số sinh viên
std::string idStr;
std::getline(std::cin, idStr);
int studentId = std::stoi(idStr);
// Đọc điểm của ba môn học (định dạng: "CourseName Score")
std::string line1, line2, line3;
std::getline(std::cin, line1);
std::getline(std::cin, line2);
std::getline(std::cin, line3);
// TODO: Phân tích từng dòng để lấy tên môn học và điểm
// Dùng std::stod() để chuyển các chuỗi điểm thành số thực
// TODO: Tạo đối tượng Student với tên và mã số sinh viên
// TODO: Thêm điểm của cả ba môn học cho sinh viên
// TODO: Hiển thị đầy đủ hồ sơ sinh viên
return 0;
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiBiên dịch và tạo bản dựng C++Tệp header và tệp nguồnNamespace và phạm viGiới thiệu về OOP trong C++Lớp và đối tượngCon trỏ thisPhương thức (hàm thành viên)Thuộc tính (dữ liệu thành viên)Cơ bản về hàm khởi tạo và hàm hủyÔn tập: máy tính đơn giản4Thuộc tính của lớp
Thành viên đối tượng và thành viên tĩnhHàm truy xuất và hàm thiết lậpHàm thành viên hằngTừ khóa mutablePhương thức và biến tĩnhHàm và lớp bạnÔn tập: Trình quản lý tài khoản ngân hàng7Kế thừa
Kế thừa cơ bảnMức truy cập trong kế thừaThứ tự gọi hàm khởi tạo và hàm hủyGhi đè phương thứcHàm ảo và VTableĐa kế thừaKế thừa ảoÔn tập: hệ phân cấp nhân viên2Quản lý bộ nhớ
Bộ nhớ ngăn xếp và heapCon trỏ và tham chiếuBộ nhớ động (new/delete)Con trỏ thông minh trong C++RAII trong C++Ôn tập: Trình quản lý mảng động5Tính đóng gói
Phạm vi truy cập trong C++Tìm hiểu sâu về phạm vi truy cậpẨn thông tinStruct và lớpLớp lồng nhau và lớp bên trongÔn tập: hệ thống hồ sơ sinh viên8Đa hình
Đa hình lúc biên dịch và khi chạyNạp chồng hàmÔn lại hàm ảoHàm ảo thuần túyLớp trừu tượngThiết kế interface trong C++Ép kiểu động và RTTIÔn tập: Máy tính hình học3Hàm khởi tạo và hàm hủy
Hàm khởi tạo mặc địnhHàm khởi tạo có tham sốHàm khởi tạo sao chépHàm khởi tạo di chuyểnDanh sách khởi tạoHàm khởi tạo ủy quyềnTìm hiểu sâu về hàm hủyQuy tắc 3 / 5 / 0Ôn tập: lớp chuỗi6Nạp chồng toán tử
Giới thiệu về nạp chồng toán tửNạp chồng toán tử số họcNạp chồng toán tử so sánhToán tử luồngNạp chồng toán tử gánNạp chồng toán tử [] và ()Toán tử chuyển đổi kiểuÔn tập: lớp ma trận9Mẫu
Mẫu hàmMẫu lớpChuyên biệt hóa mẫuMẫu biến tham sốCơ bản về SFINAE và đặc điểm kiểuÔn tập: vùng chứa tổng quátTự luyện tập: Trình biên dịch C++ online