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

学习建议:


📝 作业

  1. **基础题 (Difficulty ⭐):定义一个 Book 类(书名、作者、价格),创建 3 个对象并输出它们的属性。

  2. **进阶题 (Difficulty ⭐⭐):实现一个继承体系:Shape(基类,纯虚函数 area())→ Circle 和 Rectangle 派生类。用多态方式调用 area。

  3. **挑战题 (Difficulty ⭐⭐⭐):实现一个"观察者模式":Subject 类维护一个 Observer 列表,Observer 是抽象基类。当 Subject 状态改变时通知所有 Observer。



Phase 5 结束!下一步:Phase 6(STL进阶)

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏