C++: 实战:OOP 综合
最后更新:2026-08-26
前面35课,我们学了C++的方方面面。
现在,是时候综合应用了。
这节课,我们要做一个完整的学生管理系统——从需求分析到代码实现,体验真正的软件开发。
1. 项目需求分析
(1) 1.1 功能需求
我们要实现的学生管理系统,具备以下功能:
| 功能模块 | 具体功能 |
|---|---|
| 学生管理 | 添加、删除、修改、查询学生 |
| 成绩管理 | 录入成绩、计算平均分、排名 |
| 数据持久化 | 保存到文件、从文件加载 |
| 用户界面 | 菜单驱动的控制台界面 |
(2) 1.2 类的设计
根据需求,我们需要设计以下类:
TEXT
📖 仅展示
Student(学生基类)
↑ 继承
UndergraduateStudent(本科生)
GraduateStudent(研究生)
Course(课程类)
Grade(成绩类)
ManagementSystem(管理系统类)
- vector<Student*> students
- vectorCourse courses
2. 基础版本实现
(1) 2.1 学生类设计
示例:学生类基础版(难度⭐⭐)
CPP
#include <iostream>
#include <string>
#include <vector>
// 学生基类
class Student {
protected:
std::string id; // 学号
std::string name; // 姓名
int age; // 年龄
std::string major; // 专业
public:
// 构造函数
Student(const std::string& id, const std::string& name, int age, const std::string& major)
: id(id), name(name), age(age), major(major) {}
// 虚函数:显示信息
virtual void display() const {
std::cout << "学号:" << id << std::endl;
std::cout << "姓名:" << name << std::endl;
std::cout << "年龄:" << age << std::endl;
std::cout << "专业:" << major << std::endl;
}
// 虚析构函数
virtual ~Student() {}
// Getter
std::string getId() const { return id; }
std::string getName() const { return name; }
};
// 本科生类
class UndergraduateStudent : public Student {
private:
int year; // 年级(1-4)
public:
UndergraduateStudent(const std::string& id, const std::string& name,
int age, const std::string& major, int year)
: Student(id, name, age, major), year(year) {}
void display() const override {
Student::display();
std::cout << "年级:" << year << "年级" << std::endl;
std::cout << "类型:本科生" << std::endl;
}
};
// 研究生类
class GraduateStudent : public Student {
private:
std::string advisor; // 导师
public:
GraduateStudent(const std::string& id, const std::string& name,
int age, const std::string& major, const std::string& advisor)
: Student(id, name, age, major), advisor(advisor) {}
void display() const override {
Student::display();
std::cout << "导师:" << advisor << std::endl;
std::cout << "类型:研究生" << std::endl;
}
};
(2) 2.2 管理系统类
示例:管理系统基础版(难度⭐⭐⭐)
▶ 示例 1:STL容器使用(难度⭐)
CPP
class ManagementSystem {
private:
std::vector<Student*> students; // 学生列表(多态)
public:
// 添加学生
void addStudent(Student* student) {
students.push_back(student);
std::cout << "添加成功!" << std::endl;
}
// 查找学生
Student* findStudent(const std::string& id) {
for (auto s : students) {
if (s->getId() == id) {
return s;
}
}
return nullptr;
}
// 显示所有学生
void displayAll() const {
if (students.empty()) {
std::cout << "暂无学生信息" << std::endl;
return;
}
for (auto s : students) {
s->display();
std::cout << "-------------------" << std::endl;
}
}
// 析构函数:释放内存
~ManagementSystem() {
for (auto s : students) {
delete s;
}
}
};
// 测试代码
int main() {
ManagementSystem sys;
// 添加本科生
sys.addStudent(new UndergraduateStudent("001", "张三", 20, "计算机", 3));
sys.addStudent(new GraduateStudent("002", "李四", 24, "软件工程", "王教授"));
// 显示所有学生
sys.displayAll();
return 0;
}
输出:
TEXT
📖 仅展示
添加成功!
暂无学生信息
-------------------
运行结果:
TEXT
📖 仅展示
添加成功!
添加成功!
学号:001
姓名:张三
年龄:20
专业:计算机
年级:3年级
类型:本科生
-------------------
学号:002
姓名:李四
年龄:24
专业:软件工程
导师:王教授
类型:研究生
-------------------
3. 完整版实现
(1) 3.1 添加更多功能
现在,我们给系统添加更多功能:
| 功能 | 实现方式 |
|---|---|
| 删除学生 | 按学号删除 |
| 修改信息 | 按学号查找,修改 |
| 成绩管理 | 添加成绩类 |
| 文件保存 | 用 ofstream 写文件 |
| 文件加载 | 用 ifstream 读文件 |
(2) 3.2 成绩类设计
CPP
// 成绩类
### ▶ 示例 2:面向对象编程演示(难度⭐)
class Grade {
private:
std::string courseId; // 课程ID
std::string courseName; // 课程名称
double score; // 分数
public:
Grade(const std::string& courseId, const std::string& courseName, double score)
: courseId(courseId), courseName(courseName), score(score) {}
void display() const {
std::cout << courseName << ":" << score << "分" << std::endl;
}
double getScore() const { return score; }
};
// 在学生类中添加成绩相关方法
class Student {
// ... 其他成员 ...
std::vectorGrade grades; // 成绩列表
public:
void addGrade(const Grade& grade) {
grades.push_back(grade);
}
void displayGrades() const {
if (grades.empty()) {
std::cout << "暂无成绩" << std::endl;
return;
}
std::cout << name << "的成绩:" << std::endl;
for (const auto& g : grades) {
g.display();
}
}
double getAverage() const {
if (grades.empty()) return 0.0;
double sum = 0;
for (const auto& g : grades) {
sum += g.getScore();
}
return sum / grades.size();
}
};
(3) 3.3 文件操作
保存学生信息到文件:
CPP
void saveToFile(const std::string& filename) {
std::ofstream file(filename);
if (!file) {
std::cout << "无法打开文件" << std::endl;
return;
}
for (auto s : students) {
file << s->getId() << ","
<< s->getName() << ","
<< s->getAge() << std::endl;
}
file.close();
std::cout << "保存成功!" << std::endl;
}
从文件加载:
CPP
void loadFromFile(const std::string& filename) {
std::ifstream file(filename);
if (!file) {
std::cout << "无法打开文件" << std::endl;
return;
}
std::string id, name, ageStr;
while (std::getline(file, id, ',')) {
std::getline(file, name, ',');
std::getline(file, ageStr);
int age = std::stoi(ageStr);
// 创建学生对象(简化版,实际要区分本科生/研究生)
students.push_back(new UndergraduateStudent(id, name, age, "未知", 1));
}
file.close();
std::cout << "加载成功!" << std::endl;
}
4. 菜单界面实现
(1) 4.1 主菜单
CPP
void showMenu() {
std::cout << "\n===== 学生管理系统 =====" << std::endl;
std::cout << "1. 添加学生" << std::endl;
std::cout << "2. 查找学生" << std::endl;
std::cout << "3. 显示所有学生" << std::endl;
std::cout << "4. 录入成绩" << std::endl;
std::cout << "5. 保存数据" << std::endl;
std::cout << "6. 加载数据" << std::endl;
std::cout << "0. 退出" << std::endl;
std::cout << "========================" << std::endl;
std::cout << "请选择:";
}
int main() {
ManagementSystem sys;
int choice;
do {
showMenu();
std::cin >> choice;
switch (choice) {
case 1:
// 添加学生
break;
case 2:
// 查找学生
break;
case 3:
sys.displayAll();
break;
case 0:
std::cout << "再见!" << std::endl;
break;
default:
std::cout << "无效选择" << std::endl;
}
} while (choice != 0);
return 0;
}
5. 项目扩展建议
(1) 5.1 功能扩展
| 功能 | 难度 | 说明 |
|---|---|---|
| 成绩统计 | ⭐⭐ | 计算平均分、排名 |
| 数据验证 | ⭐⭐ | 检查输入合法性 |
| 异常处理 | ⭐⭐⭐ | 用 try-catch 处理错误 |
| 图形界面 | ⭐⭐⭐⭐ | 用Qt或wxWidgets |
| 数据库 | ⭐⭐⭐⭐ | 用SQLite或MySQL |
(2) 5.2 代码优化
| 优化点 | 说明 |
|---|---|
| 智能指针 | 用 unique_ptr 管理内存 |
| const正确性 | 尽可能用 const |
| 异常处理 | 用 try-catch 处理文件错误 |
| 运算符重载 | 重载 << 用于输出 |
▶ 示例 3:简单的类继承体系(难度⭐)
CPP
#include <iostream>
#include <string>
class Animal {
public:
std::string name;
Animal(const std::string& n) : name(n) {}
virtual void speak() const = 0;
virtual ~Animal() {}
};
class Dog : public Animal {
public:
Dog(const std::string& n) : Animal(n) {}
void speak() const override {
std::cout << name << ": 汪汪!" << std::endl;
}
};
class Cat : public Animal {
public:
Cat(const std::string& n) : Animal(n) {}
void speak() const override {
std::cout << name << ": 喵喵!" << std::endl;
}
};
int main() {
Dog dog("旺财");
Cat cat("咪咪");
dog.speak();
cat.speak();
return 0;
}
输出:
TEXT
📖 仅展示
: 汪汪!
: 喵喵!
❓ 常见问题
Q:为什么用指针存储学生? A:为了实现多态。如果用
vectorStudent,会发生对象切片,只能调用基类方法。
Q:内存泄漏怎么办? A:用智能指针(
unique_ptr)自动管理内存,不需要手动delete。
Q:文件格式怎么设计? A:可以用: - CSV格式:简单,但功能有限 - JSON格式:功能强,需要第三方库 - 二进制格式:效率高,但不可读
Q 怎么处理中文字符?
A C++对中文支持不够好,建议: - 用
wstring + wcout - 或者用第三方库(如iconv) - 或者只存拼音/英文📖 小节
| 知识点 | 要点 |
|---|---|
| 类设计 | 基类 + 派生类,体现继承 |
| 多态 | 用指针/引用调用虚函数 |
| 文件操作 | ofstream 写,ifstream 读 |
| 内存管理 | 析构函数释放内存(或用智能指针) |
| 菜单界面 | do-while + switch |
学习建议:
- 这个项目是综合练习,务必自己敲一遍
- 先实现基础功能,再逐步扩展
- 遇到问题先查资料,培养解决问题的能力
📝 作业
-
**基础题 (Difficulty ⭐):定义一个 Book 类(书名、作者、价格),创建 3 个对象并输出它们的属性。
-
**进阶题 (Difficulty ⭐⭐):实现一个继承体系:Shape(基类,纯虚函数 area())→ Circle 和 Rectangle 派生类。用多态方式调用 area。
-
**挑战题 (Difficulty ⭐⭐⭐):实现一个"观察者模式":Subject 类维护一个 Observer 列表,Observer 是抽象基类。当 Subject 状态改变时通知所有 Observer。
- 本节介绍了 practice oop 的核心概念
- 掌握后可以编写相关的 C++ 程序
Phase 5 结束!下一步:Phase 6(STL进阶)