📣📣📣📣📣📣📣📣
✏️作者主页:瑶池酒剑仙
📋 系列专栏:C++实战宝典
🌲上一篇: C++并发编程完全指南:从多线程到无锁并发的实战宝典
📣📣📣📣📣📣📣📣
🎍逐梦编程,让中华屹立世界之巅。
🎍简单的事情重复做,重复的事情用心做,用心的事情坚持做;

文章目录
- 引言:面向对象编程的基石
- 一、类的基本概念
-
- [1.1 类的定义与对象的创建](#1.1 类的定义与对象的创建)
- [1.2 成员函数的定义方式](#1.2 成员函数的定义方式)
- 二、构造函数与析构函数
-
- [2.1 构造函数详解](#2.1 构造函数详解)
- [2.2 析构函数](#2.2 析构函数)
- [2.3 拷贝构造函数与深拷贝](#2.3 拷贝构造函数与深拷贝)
- 三、this指针与静态成员
-
- [3.1 this指针详解](#3.1 this指针详解)
- [3.2 静态成员变量](#3.2 静态成员变量)
- [3.3 静态成员函数](#3.3 静态成员函数)
- 四、常量成员与友元
-
- [4.1 const成员函数与mutable](#4.1 const成员函数与mutable)
- [4.2 友元函数与友元类](#4.2 友元函数与友元类)
- 五、继承与多态基础
-
- [5.1 继承的基本语法](#5.1 继承的基本语法)
- [5.2 虚函数与多态](#5.2 虚函数与多态)
- 六、对象内存模型
-
- [6.1 对象的内存布局](#6.1 对象的内存布局)
- [6.2 对齐与填充](#6.2 对齐与填充)
- 七、综合实战:简单的图书管理系统
- 八、类设计最佳实践
-
- [8.1 设计原则与规范](#8.1 设计原则与规范)
- [8.2 常见设计模式示例](#8.2 常见设计模式示例)
- 九、总结
-
- [9.1 类和对象核心要点](#9.1 类和对象核心要点)
- [9.2 完整示例:学生信息管理系统](#9.2 完整示例:学生信息管理系统)
- 新壁纸(雨夜论道)
引言:面向对象编程的基石
C++是一门面向对象的编程语言,而类和对象是其核心精髓所在。类(Class)是创建对象的蓝图,它封装了数据和行为;对象(Object)则是类的具体实例,在内存中占据实际空间。面向对象编程的三大特性------封装、继承、多态,都通过类和对象得以实现。掌握类和对象,就等于掌握了C++程序设计的半壁江山。本文将从类的定义开始,深入剖析构造函数、析构函数、this指针、静态成员、友元函数等核心概念,并结合内存布局、设计模式等高级话题,带您全面理解C++的面向对象机制。
一、类的基本概念
1.1 类的定义与对象的创建
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/11
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
// 类的定义
class Student {
public: // 公有访问权限
string name;
int age;
float score;
// 成员函数(方法)
void display() {
cout << "姓名: " << name << ", 年龄: " << age << ", 成绩: " << score << endl;
}
void study(int hours) {
cout << name << " 学习了 " << hours << " 小时" << endl;
score += hours * 0.5;
}
};
void classBasics() {
// 创建对象(栈上分配)
Student stu1;
stu1.name = "张三";
stu1.age = 18;
stu1.score = 85.5;
stu1.display();
stu1.study(3);
stu1.display();
// 创建对象数组
Student classRoom[3];
classRoom[0].name = "李四";
classRoom[1].name = "王五";
classRoom[2].name = "赵六";
// 指针访问成员(使用->操作符)
Student* ptr = &stu1;
ptr->study(2);
// 动态创建对象(堆上分配)
Student* pStu = new Student;
pStu->name = "动态学生";
pStu->age = 20;
pStu->score = 90.0;
pStu->display();
delete pStu; // 记得释放内存
}
// 访问权限演示
class AccessDemo {
private: // 私有:只能在类内部访问
int privateData;
protected: // 受保护:类内部和派生类可访问
int protectedData;
public: // 公有:任何地方都可访问
int publicData;
void setPrivate(int value) {
privateData = value; // 类内部可访问私有成员
}
int getPrivate() const {
return privateData;
}
};
void accessModifiers() {
AccessDemo obj;
// obj.privateData = 10; // 错误!私有成员不可访问
// obj.protectedData = 20; // 错误!受保护成员不可直接访问
obj.publicData = 30; // 正确
obj.setPrivate(100); // 通过公有接口访问私有成员
cout << "私有数据: " << obj.getPrivate() << endl;
}
1.2 成员函数的定义方式
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/11
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
// 方式1:类内定义(隐式内联)
class Point1 {
private:
int x, y;
public:
void setX(int value) { x = value; } // 类内定义
void setY(int value) { y = value; }
int getX() { return x; }
int getY() { return y; }
};
// 方式2:类外定义(使用作用域解析符::)
class Point2 {
private:
int x, y;
public:
void setX(int value);
void setY(int value);
int getX() const;
int getY() const;
};
// 类外定义成员函数
void Point2::setX(int value) {
x = value;
}
void Point2::setY(int value) {
y = value;
}
int Point2::getX() const {
return x;
}
int Point2::getY() const {
return y;
}
// 方式3:分文件组织(推荐)
// Point.h - 头文件
/*
#ifndef POINT_H
#define POINT_H
class Point {
private:
int x, y;
public:
void setX(int value);
void setY(int value);
int getX() const;
int getY() const;
};
#endif
*/
// Point.cpp - 实现文件
/*
#include "Point.h"
void Point::setX(int value) { x = value; }
void Point::setY(int value) { y = value; }
int Point::getX() const { return x; }
int Point::getY() const { return y; }
*/
void memberFunctionDefinition() {
Point2 p;
p.setX(10);
p.setY(20);
cout << "Point: (" << p.getX() << ", " << p.getY() << ")" << endl;
}
二、构造函数与析构函数
2.1 构造函数详解
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/11
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
class Book {
private:
string title;
string author;
double price;
int pages;
public:
// 1. 默认构造函数(无参数)
Book() {
title = "未知";
author = "匿名";
price = 0.0;
pages = 0;
cout << "默认构造函数被调用" << endl;
}
// 2. 带参数的构造函数
Book(const string& t, const string& a, double p, int pg) {
title = t;
author = a;
price = p;
pages = pg;
cout << "参数化构造函数被调用: " << title << endl;
}
// 3. 使用初始化列表(更高效)
Book(const string& t, const string& a)
: title(t), author(a), price(0.0), pages(0) {
cout << "初始化列表构造函数: " << title << endl;
}
// 4. 委托构造函数(C++11)
Book(const string& t) : Book(t, "未知", 0.0, 0) {
cout << "委托构造函数" << endl;
}
// 5. 拷贝构造函数
Book(const Book& other)
: title(other.title), author(other.author),
price(other.price), pages(other.pages) {
cout << "拷贝构造函数: " << title << endl;
}
void display() const {
cout << "《" << title << "》 作者:" << author
<< ", 价格:" << price << ", 页数:" << pages << endl;
}
};
void constructorDemo() {
cout << "=== 构造函数演示 ===" << endl;
Book b1; // 默认构造
Book b2("C++ Primer", "Lippman", 128.0, 1200); // 参数化构造
Book b3("Effective C++", "Meyers"); // 初始化列表构造
Book b4("Design Patterns"); // 委托构造
Book b5(b2); // 拷贝构造
b1.display();
b2.display();
b3.display();
b4.display();
b5.display();
}
// 构造函数的重载
class Date {
private:
int year, month, day;
public:
Date() : year(1970), month(1), day(1) {}
Date(int y, int m, int d) : year(y), month(m), day(d) {}
Date(int y) : year(y), month(1), day(1) {}
// 使用默认参数
Date(int y, int m = 1, int d = 1) : year(y), month(m), day(d) {}
// 注意:带有默认参数的构造函数可能与无参构造产生歧义
void show() const {
cout << year << "-" << month << "-" << day << endl;
}
};
2.2 析构函数
cpp
class ResourceManager {
private:
char* buffer;
size_t size;
public:
// 构造函数:分配资源
ResourceManager(size_t sz) : size(sz) {
buffer = new char[size];
cout << "分配 " << size << " 字节内存" << endl;
}
// 析构函数:释放资源(~类名,无参数,无返回值)
~ResourceManager() {
delete[] buffer;
cout << "释放 " << size << " 字节内存" << endl;
}
void setData(const char* str) {
strncpy(buffer, str, size - 1);
buffer[size - 1] = '\0';
}
void display() const {
cout << "数据: " << buffer << endl;
}
};
// 演示析构函数自动调用
void destructorDemo() {
cout << "进入函数" << endl;
ResourceManager res(100);
res.setData("Hello, RAII!");
res.display();
cout << "即将离开函数" << endl;
// res的析构函数自动调用,释放内存
}
// 析构函数调用顺序(后创建先析构)
class OrderTest {
private:
int id;
public:
OrderTest(int i) : id(i) {
cout << "对象 " << id << " 构造" << endl;
}
~OrderTest() {
cout << "对象 " << id << " 析构" << endl;
}
};
void destructorOrder() {
OrderTest o1(1);
OrderTest o2(2);
{
OrderTest o3(3);
OrderTest o4(4);
} // o4, o3在此析构
OrderTest o5(5);
} // o5, o2, o1依次析构
// 虚析构函数(用于多态场景)
class Base {
public:
virtual ~Base() {
cout << "Base析构" << endl;
}
};
class Derived : public Base {
private:
int* data;
public:
Derived() : data(new int[100]) {}
~Derived() override {
delete[] data;
cout << "Derived析构" << endl;
}
};
void virtualDestructorDemo() {
Base* ptr = new Derived();
delete ptr; // 如果Base析构不是virtual,则Derived析构不会被调用
}
2.3 拷贝构造函数与深拷贝
cpp
// 浅拷贝问题演示
class ShallowCopy {
private:
int* data;
public:
ShallowCopy(int value) {
data = new int(value);
cout << "构造: " << *data << endl;
}
// 默认拷贝构造函数执行浅拷贝
// 两个对象的data指针指向同一块内存
~ShallowCopy() {
delete data;
cout << "析构" << endl;
}
int getValue() const { return *data; }
};
void shallowCopyProblem() {
ShallowCopy obj1(42);
ShallowCopy obj2 = obj1; // 浅拷贝,两个指针指向同一内存
// 析构时会double free,程序崩溃!
}
// 深拷贝:正确实现
class DeepCopy {
private:
int* data;
public:
DeepCopy(int value) {
data = new int(value);
cout << "构造: " << *data << endl;
}
// 深拷贝构造函数
DeepCopy(const DeepCopy& other) {
data = new int(*other.data); // 重新分配内存
cout << "深拷贝构造: " << *data << endl;
}
// 深拷贝赋值运算符
DeepCopy& operator=(const DeepCopy& other) {
if (this != &other) {
delete data;
data = new int(*other.data);
cout << "深拷贝赋值: " << *data << endl;
}
return *this;
}
~DeepCopy() {
delete data;
cout << "析构: " << (data ? "释放" : "空指针") << endl;
}
void setValue(int value) { *data = value; }
int getValue() const { return *data; }
};
void deepCopyDemo() {
DeepCopy a(100);
DeepCopy b = a; // 深拷贝构造
DeepCopy c(200);
c = a; // 深拷贝赋值
b.setValue(999);
cout << "a: " << a.getValue() << ", b: " << b.getValue() << endl;
// a和b独立,互不影响
}
三、this指针与静态成员
3.1 this指针详解
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/11
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
class Counter {
private:
int count;
public:
Counter() : count(0) {}
// this指针指向当前对象
Counter& increment() {
count++;
return *this; // 返回当前对象的引用,支持链式调用
}
Counter& decrement() {
count--;
return *this;
}
void display() const {
cout << "当前计数: " << count << endl;
}
// 参数与成员同名时使用this区分
void setCount(int count) {
this->count = count; // this->count是成员变量,count是参数
}
};
void thisPointerDemo() {
Counter c;
// 链式调用(方法级联)
c.increment().increment().decrement().increment();
c.display(); // 计数: 2
}
// 使用this指针实现比较
class Person {
private:
string name;
int age;
public:
Person(const string& n, int a) : name(n), age(a) {}
// const成员函数中的this是const指针
bool isOlderThan(const Person& other) const {
return this->age > other.age; // this->可省略
}
Person* getThis() {
return this; // 返回当前对象的指针
}
const Person* getThis() const {
return this;
}
};
void personCompare() {
Person alice("Alice", 25);
Person bob("Bob", 30);
if (bob.isOlderThan(alice)) {
cout << "Bob比Alice年龄大" << endl;
}
// this指针的值等于对象的地址
cout << "对象地址: " << &alice << endl;
cout << "this指针: " << alice.getThis() << endl;
}
3.2 静态成员变量
cpp
class Employee {
private:
string name;
int id;
// 静态成员变量:属于类,不属于任何对象
static int totalEmployees; // 声明
static int nextId; // 用于生成唯一ID
public:
Employee(const string& n) : name(n) {
id = nextId++;
totalEmployees++;
cout << "创建员工: " << name << ", ID: " << id
<< ", 总人数: " << totalEmployees << endl;
}
~Employee() {
totalEmployees--;
cout << "销毁员工: " << name << ", 剩余: " << totalEmployees << endl;
}
// 静态成员函数:只能访问静态成员
static int getTotalEmployees() {
return totalEmployees;
}
static void showStatistics() {
cout << "=== 员工统计 ===" << endl;
cout << "总人数: " << totalEmployees << endl;
cout << "下一个ID: " << nextId << endl;
}
void display() const {
cout << "员工: " << name << ", ID: " << id << endl;
}
};
// 静态成员变量的定义和初始化(必须在类外)
int Employee::totalEmployees = 0;
int Employee::nextId = 1;
void staticMemberDemo() {
cout << "初始总人数: " << Employee::getTotalEmployees() << endl;
Employee e1("张三");
Employee e2("李四");
Employee e3("王五");
Employee::showStatistics(); // 通过类名调用静态函数
{
Employee e4("赵六");
cout << "当前总人数: " << Employee::getTotalEmployees() << endl;
} // e4被销毁
cout << "最终总人数: " << Employee::getTotalEmployees() << endl;
}
// 静态常量成员
class MathConstants {
public:
static const double PI; // 在类内声明
static constexpr double E = 2.718281828459045; // C++11字面量常量
static double circleArea(double radius) {
return PI * radius * radius;
}
};
// 类外定义静态常量成员
const double MathConstants::PI = 3.141592653589793;
3.3 静态成员函数
cpp
// 静态成员函数的特点和使用场景
class Database {
private:
static Database* instance;
string connectionString;
bool connected;
// 私有构造函数(单例模式)
Database() : connectionString("default"), connected(false) {}
public:
// 禁止拷贝
Database(const Database&) = delete;
Database& operator=(const Database&) = delete;
// 静态方法获取单例实例
static Database& getInstance() {
if (instance == nullptr) {
instance = new Database();
}
return *instance;
}
static void setConnection(const string& conn) {
getInstance().connectionString = conn;
}
void connect() {
cout << "连接到: " << connectionString << endl;
connected = true;
}
void disconnect() {
cout << "断开连接" << endl;
connected = false;
}
static void cleanup() {
delete instance;
instance = nullptr;
}
};
// 初始化静态成员
Database* Database::instance = nullptr;
void staticFunctionDemo() {
// 通过类名调用静态方法
Database::setConnection("mysql://localhost:3306/mydb");
Database& db = Database::getInstance();
db.connect();
db.disconnect();
Database::cleanup();
}
// 静态成员函数的限制
class StaticTest {
private:
int instanceData;
static int staticData;
public:
void instanceMethod() {
instanceData = 10; // 可以访问实例数据
staticData = 20; // 可以访问静态数据
}
static void staticMethod() {
// instanceData = 10; // 错误!不能访问非静态成员
staticData = 20; // 只能访问静态成员
// 不能使用this指针(没有this)
// 可以创建对象来访问非静态成员
StaticTest obj;
obj.instanceData = 30;
}
};
int StaticTest::staticData = 0;
四、常量成员与友元
4.1 const成员函数与mutable
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/11
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
class ConstDemo {
private:
int data;
mutable int cacheData; // mutable成员可在const函数中修改
mutable int accessCount;
public:
ConstDemo(int d) : data(d), cacheData(0), accessCount(0) {}
// const成员函数:承诺不修改对象状态
int getData() const {
// data = 10; // 错误!不能修改普通成员
accessCount++; // 可以修改mutable成员
return data;
}
// 非const成员函数
void setData(int d) {
data = d;
}
// const重载
int& getRef() {
cout << "非const版本" << endl;
return data;
}
const int& getRef() const {
cout << "const版本" << endl;
return data;
}
int getAccessCount() const {
return accessCount;
}
};
void constMemberDemo() {
// const对象只能调用const成员函数
const ConstDemo constObj(100);
cout << "const对象读取: " << constObj.getData() << endl;
// constObj.setData(200); // 错误!const对象不能调用非const函数
ConstDemo nonConstObj(200);
nonConstObj.setData(300); // 调用非const版本
int& ref = nonConstObj.getRef(); // 非const版本
const ConstDemo& constRef = nonConstObj;
constRef.getRef(); // const版本
}
// 成员初始化列表中的const成员
class ConstMember {
private:
const int id; // const成员必须在初始化列表中初始化
const string name;
static const int MAX_COUNT = 100; // 静态const可在类内初始化
public:
ConstMember(int i, const string& n) : id(i), name(n) {
// id = i; // 错误!不能在构造函数体内赋值
}
void display() const {
cout << "ID: " << id << ", Name: " << name
<< ", MAX: " << MAX_COUNT << endl;
}
};
4.2 友元函数与友元类
cpp
// 前向声明
class Vector2D;
// 友元函数
class Vector2D {
private:
double x, y;
public:
Vector2D(double x = 0, double y = 0) : x(x), y(y) {}
// 声明友元函数(非成员函数可以访问私有成员)
friend Vector2D operator+(const Vector2D& a, const Vector2D& b);
friend ostream& operator<<(ostream& os, const Vector2D& v);
// 声明其他类的成员函数为友元
friend void Matrix::transform(Vector2D& v); // 前向声明需要
// 普通成员函数
void display() const {
cout << "(" << x << ", " << y << ")" << endl;
}
};
// 友元函数实现
Vector2D operator+(const Vector2D& a, const Vector2D& b) {
return Vector2D(a.x + b.x, a.y + b.y); // 可直接访问私有成员
}
ostream& operator<<(ostream& os, const Vector2D& v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
// 友元类
class Matrix {
private:
double data[2][2];
public:
Matrix(double a=1, double b=0, double c=0, double d=1) {
data[0][0] = a; data[0][1] = b;
data[1][0] = c; data[1][1] = d;
}
// 声明友元类
friend class VectorTransformer;
};
// 友元类可以访问Matrix的私有成员
class VectorTransformer {
public:
static Vector2D transform(const Matrix& m, const Vector2D& v) {
double x = m.data[0][0] * v.x + m.data[0][1] * v.y;
double y = m.data[1][0] * v.x + m.data[1][1] * v.y;
return Vector2D(x, y);
}
};
void friendDemo() {
Vector2D v1(3, 4);
Vector2D v2(1, 2);
Vector2D v3 = v1 + v2;
cout << "v1 = " << v1 << endl;
cout << "v2 = " << v2 << endl;
cout << "v1 + v2 = " << v3 << endl;
Matrix m(2, 0, 0, 2); // 缩放2倍
Vector2D transformed = VectorTransformer::transform(m, v1);
cout << "变换后: " << transformed << endl;
}
// 友元的注意事项
class FriendNote {
private:
int secret;
// 友元关系不能继承
friend class FriendClass;
// 友元关系是单向的(A是B的友元,不代表B是A的友元)
// 友元关系不能被传递(A是B的友元,B是C的友元,不代表A是C的友元)
};
五、继承与多态基础
5.1 继承的基本语法
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/11
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
// 基类
class Animal {
protected: // 派生类可访问
string name;
int age;
public:
Animal(const string& n, int a) : name(n), age(a) {
cout << "Animal构造: " << name << endl;
}
virtual ~Animal() {
cout << "Animal析构: " << name << endl;
}
virtual void speak() const {
cout << name << " 发出动物叫声" << endl;
}
void eat() const {
cout << name << " 正在吃东西" << endl;
}
string getName() const { return name; }
};
// 公有继承
class Dog : public Animal {
private:
string breed; // 品种
public:
Dog(const string& n, int a, const string& b)
: Animal(n, a), breed(b) {
cout << "Dog构造: " << name << " (" << breed << ")" << endl;
}
~Dog() override {
cout << "Dog析构: " << name << endl;
}
void speak() const override {
cout << name << " 汪汪汪!" << endl;
}
void wagTail() const {
cout << name << " 摇尾巴" << endl;
}
};
// 私有继承
class PrivateDerived : private Animal {
// 基类的public/protected成员变成private
public:
using Animal::getName; // 使getName在public区域可见
};
void inheritanceDemo() {
cout << "=== 继承演示 ===" << endl;
Dog dog("旺财", 3, "金毛");
dog.speak(); // 重写的方法
dog.eat(); // 继承的方法
dog.wagTail(); // 派生类自己的方法
// 向上转型(派生类到基类)
Animal* ptr = &dog;
ptr->speak(); // 多态:调用Dog的speak
ptr->eat(); // 调用Animal的eat
}
// 继承中的构造函数和析构函数调用顺序
class Base1 {
public:
Base1() { cout << "Base1构造" << endl; }
~Base1() { cout << "Base1析构" << endl; }
};
class Base2 {
public:
Base2() { cout << "Base2构造" << endl; }
~Base2() { cout << "Base2析构" << endl; }
};
class Derived1 : public Base1, public Base2 {
private:
Base1 member1;
Base2 member2;
public:
Derived1() {
cout << "Derived1构造" << endl;
}
~Derived1() {
cout << "Derived1析构" << endl;
}
};
void orderDemo() {
Derived1 d;
// 构造顺序:基类(按声明顺序)-> 成员(按声明顺序)-> 派生类
// 析构顺序相反
}
5.2 虚函数与多态
cpp
// 虚函数表示例
class Shape {
public:
virtual double area() const = 0; // 纯虚函数,抽象类
virtual void draw() const {
cout << "绘制形状" << endl;
}
virtual ~Shape() = default;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
void draw() const override {
cout << "绘制圆形,半径: " << radius << endl;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override {
return width * height;
}
void draw() const override {
cout << "绘制矩形,宽: " << width << ", 高: " << height << endl;
}
};
void polymorphismDemo() {
vector<Shape*> shapes;
shapes.push_back(new Circle(5));
shapes.push_back(new Rectangle(4, 6));
shapes.push_back(new Circle(3));
for (Shape* s : shapes) {
s->draw();
cout << "面积: " << s->area() << endl;
}
// 释放内存
for (Shape* s : shapes) {
delete s;
}
}
// 虚函数表(vtable)的概念
class VTableDemo {
public:
virtual void func1() { cout << "VTableDemo::func1" << endl; }
virtual void func2() { cout << "VTableDemo::func2" << endl; }
void func3() { cout << "VTableDemo::func3 (非虚)" << endl; }
};
class DerivedVTable : public VTableDemo {
public:
void func1() override { cout << "DerivedVTable::func1" << endl; }
virtual void func4() { cout << "DerivedVTable::func4" << endl; }
};
void vtableExplanation() {
VTableDemo* ptr = new DerivedVTable();
ptr->func1(); // 通过虚表调用派生类版本
ptr->func2(); // 通过虚表调用基类版本
ptr->func3(); // 非虚函数,编译时绑定
delete ptr;
}
六、对象内存模型
6.1 对象的内存布局
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/04/04
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
#include <cstddef>
// 空类的大小
class Empty {};
// 带成员变量的类
class DataMembers {
private:
char c; // 1字节
int i; // 4字节(可能对齐到4)
double d; // 8字节
// 实际大小可能大于1+4+8=13,因为有内存对齐
};
// 带虚函数的类(有虚表指针)
class WithVtable {
public:
int x;
virtual void func() {}
};
// 继承中的内存布局
class BaseLayout {
public:
int baseData;
virtual void baseFunc() {}
};
class DerivedLayout : public BaseLayout {
public:
int derivedData;
void baseFunc() override {}
virtual void derivedFunc() {}
};
void memoryLayout() {
cout << "=== 对象内存大小 ===" << endl;
cout << "Empty类大小: " << sizeof(Empty) << " 字节" << endl; // 1字节(占位)
cout << "DataMembers类大小: " << sizeof(DataMembers) << " 字节" << endl;
cout << "WithVtable类大小: " << sizeof(WithVtable) << " 字节" << endl;
cout << "BaseLayout类大小: " << sizeof(BaseLayout) << " 字节" << endl;
cout << "DerivedLayout类大小: " << sizeof(DerivedLayout) << " 字节" << endl;
// 成员偏移量
DataMembers obj;
cout << "\n=== 成员偏移量 ===" << endl;
cout << "c的偏移: " << offsetof(DataMembers, c) << endl;
cout << "i的偏移: " << offsetof(DataMembers, i) << endl;
cout << "d的偏移: " << offsetof(DataMembers, d) << endl;
}
// 对象的内存分配
class MemoryObject {
public:
int a;
int b;
static int staticValue; // 静态成员不属于对象
void method1() {} // 函数代码不在对象中
virtual void vmethod() {} // 虚函数表指针在对象中
};
int MemoryObject::staticValue = 0;
void memoryAllocation() {
// 栈上分配
MemoryObject stackObj;
stackObj.a = 10;
// 堆上分配
MemoryObject* heapObj = new MemoryObject();
heapObj->b = 20;
// 静态存储区
static MemoryObject staticObj;
delete heapObj;
}
6.2 对齐与填充
cpp
// 内存对齐控制
#pragma pack(push, 1) // 按1字节对齐
struct PackedStruct {
char c;
int i;
short s;
};
#pragma pack(pop)
struct DefaultStruct {
char c;
int i;
short s;
};
// 手动对齐
struct AlignedStruct {
char c;
char padding1[3]; // 手动填充
int i;
short s;
char padding2[2]; // 手动填充
};
void alignmentDemo() {
cout << "\n=== 内存对齐对比 ===" << endl;
cout << "默认对齐大小: " << sizeof(DefaultStruct) << " 字节" << endl;
cout << "紧凑对齐(1字节): " << sizeof(PackedStruct) << " 字节" << endl;
cout << "手动对齐: " << sizeof(AlignedStruct) << " 字节" << endl;
// C++11 alignas指定对齐
struct alignas(16) Aligned16 {
char data[8];
};
cout << "16字节对齐: " << sizeof(Aligned16) << " 字节" << endl;
cout << "对齐要求: " << alignof(Aligned16) << " 字节" << endl;
}
七、综合实战:简单的图书管理系统
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/05/10
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
#include <vector>
#include <algorithm>
#include <iomanip>
// 图书类
class Book {
private:
string isbn;
string title;
string author;
double price;
int stock;
static int totalBooks;
public:
Book(const string& isbn, const string& title,
const string& author, double price, int stock)
: isbn(isbn), title(title), author(author),
price(price), stock(stock) {
totalBooks++;
}
~Book() {
totalBooks--;
}
// 拷贝构造(深拷贝)
Book(const Book& other)
: isbn(other.isbn), title(other.title),
author(other.author), price(other.price),
stock(other.stock) {
totalBooks++;
}
// 赋值运算符
Book& operator=(const Book& other) {
if (this != &other) {
isbn = other.isbn;
title = other.title;
author = other.author;
price = other.price;
stock = other.stock;
}
return *this;
}
// getter方法
string getIsbn() const { return isbn; }
string getTitle() const { return title; }
string getAuthor() const { return author; }
double getPrice() const { return price; }
int getStock() const { return stock; }
void setStock(int s) { stock = s; }
bool borrow() {
if (stock > 0) {
stock--;
return true;
}
return false;
}
void returnBook() {
stock++;
}
void display() const {
cout << left << setw(15) << isbn
<< setw(25) << title
<< setw(15) << author
<< setw(8) << price
<< setw(6) << stock << endl;
}
static int getTotalBooks() {
return totalBooks;
}
// 友元函数:比较运算符
friend bool operator==(const Book& a, const Book& b) {
return a.isbn == b.isbn;
}
};
int Book::totalBooks = 0;
// 借阅记录类
class BorrowRecord {
private:
string isbn;
string borrower;
time_t borrowDate;
time_t returnDate;
bool returned;
public:
BorrowRecord(const string& isbn, const string& borrower)
: isbn(isbn), borrower(borrower),
borrowDate(time(nullptr)), returned(false), returnDate(0) {}
void returnBook() {
returnDate = time(nullptr);
returned = true;
}
void display() const {
cout << "ISBN: " << isbn << ", 借阅人: " << borrower
<< ", 借阅时间: " << ctime(&borrowDate);
if (returned) {
cout << ", 归还时间: " << ctime(&returnDate);
} else {
cout << ", 状态: 未归还" << endl;
}
}
bool isReturned() const { return returned; }
string getIsbn() const { return isbn; }
};
// 图书馆类
class Library {
private:
vector<Book> books;
vector<BorrowRecord> records;
mutable mutex mtx; // 线程安全(演示用)
// 查找图书(私有辅助函数)
int findBook(const string& isbn) const {
for (size_t i = 0; i < books.size(); ++i) {
if (books[i].getIsbn() == isbn) {
return i;
}
}
return -1;
}
public:
// 添加图书
void addBook(const Book& book) {
lock_guard<mutex> lock(mtx);
int index = findBook(book.getIsbn());
if (index != -1) {
// 已存在,增加库存
books[index].setStock(books[index].getStock() + book.getStock());
cout << "增加库存: " << book.getTitle() << endl;
} else {
books.push_back(book);
cout << "添加新书: " << book.getTitle() << endl;
}
}
// 删除图书
bool removeBook(const string& isbn) {
lock_guard<mutex> lock(mtx);
auto it = find_if(books.begin(), books.end(),
[&isbn](const Book& b) { return b.getIsbn() == isbn; });
if (it != books.end()) {
books.erase(it);
cout << "删除图书: " << isbn << endl;
return true;
}
return false;
}
// 借阅图书
bool borrowBook(const string& isbn, const string& borrower) {
lock_guard<mutex> lock(mtx);
int index = findBook(isbn);
if (index != -1 && books[index].borrow()) {
records.emplace_back(isbn, borrower);
cout << borrower << " 借阅成功: " << books[index].getTitle() << endl;
return true;
}
cout << "借阅失败: 图书不存在或库存不足" << endl;
return false;
}
// 归还图书
bool returnBook(const string& isbn, const string& borrower) {
lock_guard<mutex> lock(mtx);
int index = findBook(isbn);
if (index != -1) {
books[index].returnBook();
// 查找并更新借阅记录
for (auto& record : records) {
if (record.getIsbn() == isbn && !record.isReturned()) {
record.returnBook();
cout << borrower << " 归还成功: " << books[index].getTitle() << endl;
return true;
}
}
}
cout << "归还失败: 未找到借阅记录" << endl;
return false;
}
// 搜索图书(const成员函数)
void searchByTitle(const string& title) const {
lock_guard<mutex> lock(mtx);
cout << "\n=== 搜索结果(标题包含 \"" << title << "\")===" << endl;
cout << left << setw(15) << "ISBN" << setw(25) << "书名"
<< setw(15) << "作者" << setw(8) << "价格"
<< setw(6) << "库存" << endl;
cout << string(70, '-') << endl;
for (const auto& book : books) {
if (book.getTitle().find(title) != string::npos) {
book.display();
}
}
}
void displayAll() const {
lock_guard<mutex> lock(mtx);
cout << "\n=== 图书馆藏书 ===" << endl;
cout << left << setw(15) << "ISBN" << setw(25) << "书名"
<< setw(15) << "作者" << setw(8) << "价格"
<< setw(6) << "库存" << endl;
cout << string(70, '-') << endl;
for (const auto& book : books) {
book.display();
}
cout << "\n总藏书种类: " << books.size()
<< ", 总册数: " << Book::getTotalBooks() << endl;
}
void displayBorrowRecords() const {
lock_guard<mutex> lock(mtx);
cout << "\n=== 借阅记录 ===" << endl;
for (const auto& record : records) {
record.display();
}
}
};
void librarySystemDemo() {
Library lib;
// 添加图书
lib.addBook(Book("978-7-121-12345-6", "C++ Primer", "Lippman", 128.0, 5));
lib.addBook(Book("978-7-302-23456-7", "Effective C++", "Meyers", 89.0, 3));
lib.addBook(Book("978-7-111-34567-8", "Design Patterns", "Gamma", 158.0, 2));
lib.addBook(Book("978-7-121-12345-6", "C++ Primer", "Lippman", 128.0, 3)); // 增加库存
// 显示藏书
lib.displayAll();
// 借阅图书
lib.borrowBook("978-7-121-12345-6", "张三");
lib.borrowBook("978-7-302-23456-7", "李四");
lib.borrowBook("978-7-111-34567-8", "王五");
lib.borrowBook("978-7-121-12345-6", "赵六");
// 再次显示(库存变化)
lib.displayAll();
// 归还图书
lib.returnBook("978-7-121-12345-6", "张三");
// 搜索
lib.searchByTitle("C++");
// 显示借阅记录
lib.displayBorrowRecords();
// 显示统计信息
cout << "\n=== 统计信息 ===" << endl;
cout << "总图书种类: " << Book::getTotalBooks() << endl;
}
八、类设计最佳实践
8.1 设计原则与规范
代码如下(示例):
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/04/12
* IDE 版 本: Visual Studio 2026
* 项目版本: 1.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
// 原则1:单一职责原则
// 好的设计:一个类只负责一件事
class Logger {
public:
void log(const string& message) {
cout << "[LOG] " << message << endl;
}
};
class DataProcessor {
public:
int process(int data) {
return data * 2;
}
};
// 不好的设计:一个类做太多事情
class BadDesign {
public:
void log(const string& msg) { }
int process(int data) { return data; }
void saveToFile(const string& data) { }
void sendNetwork(const string& data) { }
};
// 原则2:封装变化
class PaymentStrategy { // 抽象接口
public:
virtual void pay(double amount) = 0;
virtual ~PaymentStrategy() = default;
};
class CreditCardPayment : public PaymentStrategy {
public:
void pay(double amount) override {
cout << "信用卡支付: " << amount << endl;
}
};
class WeChatPayment : public PaymentStrategy {
public:
void pay(double amount) override {
cout << "微信支付: " << amount << endl;
}
};
// 原则3:优先使用组合而非继承
class Engine {
public:
void start() { cout << "引擎启动" << endl; }
};
class Car {
private:
Engine engine; // 组合
public:
void start() {
engine.start();
cout << "汽车启动" << endl;
}
};
// 原则4:接口隔离
class Printable {
public:
virtual void print() = 0;
virtual ~Printable() = default;
};
class Scannable {
public:
virtual void scan() = 0;
virtual ~Scannable() = default;
};
// 而不是定义一个巨大的接口
8.2 常见设计模式示例
cpp
// 单例模式(线程安全)
class ThreadSafeSingleton {
private:
static unique_ptr<ThreadSafeSingleton> instance;
static mutex mtx;
ThreadSafeSingleton() = default;
public:
static ThreadSafeSingleton& getInstance() {
if (instance == nullptr) {
lock_guard<mutex> lock(mtx);
if (instance == nullptr) {
instance = unique_ptr<ThreadSafeSingleton>(new ThreadSafeSingleton());
}
}
return *instance;
}
void doSomething() {
cout << "Singleton instance working" << endl;
}
ThreadSafeSingleton(const ThreadSafeSingleton&) = delete;
ThreadSafeSingleton& operator=(const ThreadSafeSingleton&) = delete;
};
unique_ptr<ThreadSafeSingleton> ThreadSafeSingleton::instance = nullptr;
mutex ThreadSafeSingleton::mtx;
// 工厂模式
class Product {
public:
virtual void use() = 0;
virtual ~Product() = default;
};
class ConcreteProductA : public Product {
public:
void use() override { cout << "使用产品A" << endl; }
};
class ConcreteProductB : public Product {
public:
void use() override { cout << "使用产品B" << endl; }
};
class Factory {
public:
static unique_ptr<Product> createProduct(char type) {
switch (type) {
case 'A': return make_unique<ConcreteProductA>();
case 'B': return make_unique<ConcreteProductB>();
default: return nullptr;
}
}
};
// 建造者模式
class Computer {
private:
string cpu;
string memory;
string storage;
public:
void setCPU(const string& c) { cpu = c; }
void setMemory(const string& m) { memory = m; }
void setStorage(const string& s) { storage = s; }
void show() const {
cout << "Computer: CPU=" << cpu << ", Memory=" << memory
<< ", Storage=" << storage << endl;
}
};
class ComputerBuilder {
private:
Computer computer;
public:
ComputerBuilder& setCPU(const string& cpu) {
computer.setCPU(cpu);
return *this;
}
ComputerBuilder& setMemory(const string& memory) {
computer.setMemory(memory);
return *this;
}
ComputerBuilder& setStorage(const string& storage) {
computer.setStorage(storage);
return *this;
}
Computer build() {
return computer;
}
};
void designPatternsDemo() {
// 单例
ThreadSafeSingleton::getInstance().doSomething();
// 工厂
auto product = Factory::createProduct('A');
product->use();
// 建造者
Computer pc = ComputerBuilder()
.setCPU("Intel i7")
.setMemory("16GB")
.setStorage("512GB SSD")
.build();
pc.show();
}
九、总结
9.1 类和对象核心要点
| 概念 | 说明 | 要点 |
|---|---|---|
| 封装 | 数据隐藏 | 使用private/protected/public |
| 继承 | 代码复用 | 支持单继承,可多重继承 |
| 多态 | 接口统一 | 虚函数、纯虚函数、抽象类 |
| 构造函数 | 对象初始化 | 可重载、初始化列表、委托构造 |
| 析构函数 | 资源释放 | 虚析构用于多态 |
| this指针 | 对象自身 | const成员函数中为const指针 |
| 静态成员 | 类级别共享 | 类外定义、静态函数只能访问静态成员 |
| 友元 | 特权访问 | 破坏封装,谨慎使用 |
9.2 完整示例:学生信息管理系统
cpp
/*-----------------------------------【程序说明】----------------------------
* 项目命题: C++实战宝典
* 代码所属: 瑶池酒剑仙(枫之剑客)
* 作者: 阿甘
* 开发时间: 2026/04/04
* IDE 版 本: Visual Studio 2026
* 项目版本: 2.0.0.1
*---------------------------------------------------------------------------*/
//原文链接:https://ganzp1688.blog.csdn.net/?type=blog
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <map>
#include <memory>
#include <stdexcept>
#include <ctime>
using namespace std;
// ====================== 课程类 ======================
class Course {
private:
string courseId; // 课程编号
string courseName; // 课程名称
int credit; // 学分
int hours; // 学时
public:
Course() : credit(0), hours(0) {}
Course(const string& id, const string& name, int cred, int hr)
: courseId(id), courseName(name), credit(cred), hours(hr) {}
// Getter方法
string getCourseId() const { return courseId; }
string getCourseName() const { return courseName; }
int getCredit() const { return credit; }
int getHours() const { return hours; }
// Setter方法
void setCourseName(const string& name) { courseName = name; }
void setCredit(int cred) { credit = cred; }
void setHours(int hr) { hours = hr; }
void display() const {
cout << left << setw(12) << courseId
<< setw(20) << courseName
<< setw(8) << credit
<< setw(8) << hours << endl;
}
// 序列化
string serialize() const {
return courseId + "|" + courseName + "|" +
to_string(credit) + "|" + to_string(hours);
}
// 反序列化
static Course deserialize(const string& data) {
stringstream ss(data);
string id, name, creditStr, hoursStr;
getline(ss, id, '|');
getline(ss, name, '|');
getline(ss, creditStr, '|');
getline(ss, hoursStr, '|');
return Course(id, name, stoi(creditStr), stoi(hoursStr));
}
};
// ====================== 成绩类 ======================
class Score {
private:
string courseId;
double score;
string examTime; // 考试时间
string grade; // 等级(优/良/中/及格/不及格)
void calculateGrade() {
if (score >= 90) grade = "优秀";
else if (score >= 80) grade = "良好";
else if (score >= 70) grade = "中等";
else if (score >= 60) grade = "及格";
else grade = "不及格";
}
public:
Score() : score(0.0) {}
Score(const string& cid, double s, const string& time = "")
: courseId(cid), score(s), examTime(time) {
calculateGrade();
}
string getCourseId() const { return courseId; }
double getScore() const { return score; }
string getGrade() const { return grade; }
string getExamTime() const { return examTime; }
void setScore(double s) {
score = s;
calculateGrade();
}
void display() const {
cout << left << setw(12) << courseId
<< setw(10) << fixed << setprecision(1) << score
<< setw(10) << grade
<< setw(20) << examTime << endl;
}
string serialize() const {
return courseId + "|" + to_string(score) + "|" + examTime;
}
static Score deserialize(const string& data) {
stringstream ss(data);
string cid, scoreStr, time;
getline(ss, cid, '|');
getline(ss, scoreStr, '|');
getline(ss, time, '|');
return Score(cid, stod(scoreStr), time);
}
};
// ====================== 学生类 ======================
class Student {
private:
string stuId; // 学号
string name; // 姓名
string gender; // 性别
int age; // 年龄
string className; // 班级
string phone; // 电话
string email; // 邮箱
string address; // 地址
vector<Score> scores; // 成绩列表
static int totalStudents;
public:
// 构造函数
Student() : age(0) {}
Student(const string& id, const string& n, const string& g,
int a, const string& cls, const string& p = "",
const string& em = "", const string& addr = "")
: stuId(id), name(n), gender(g), age(a), className(cls),
phone(p), email(em), address(addr) {
totalStudents++;
}
// 拷贝构造
Student(const Student& other)
: stuId(other.stuId), name(other.name), gender(other.gender),
age(other.age), className(other.className), phone(other.phone),
email(other.email), address(other.address), scores(other.scores) {
totalStudents++;
}
// 析构函数
~Student() {
totalStudents--;
}
// 赋值运算符
Student& operator=(const Student& other) {
if (this != &other) {
stuId = other.stuId;
name = other.name;
gender = other.gender;
age = other.age;
className = other.className;
phone = other.phone;
email = other.email;
address = other.address;
scores = other.scores;
}
return *this;
}
// ========== Getter方法 ==========
string getStuId() const { return stuId; }
string getName() const { return name; }
string getGender() const { return gender; }
int getAge() const { return age; }
string getClassName() const { return className; }
string getPhone() const { return phone; }
string getEmail() const { return email; }
string getAddress() const { return address; }
const vector<Score>& getScores() const { return scores; }
// ========== Setter方法 ==========
void setName(const string& n) { name = n; }
void setGender(const string& g) { gender = g; }
void setAge(int a) { age = a; }
void setClassName(const string& cls) { className = cls; }
void setPhone(const string& p) { phone = p; }
void setEmail(const string& em) { email = em; }
void setAddress(const string& addr) { address = addr; }
// ========== 成绩管理 ==========
void addScore(const Score& score) {
// 检查是否已有该课程成绩
for (auto& s : scores) {
if (s.getCourseId() == score.getCourseId()) {
cout << "该课程成绩已存在,是否更新?(y/n): ";
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y') {
s = score;
cout << "成绩已更新" << endl;
}
return;
}
}
scores.push_back(score);
cout << "成绩添加成功" << endl;
}
bool removeScore(const string& courseId) {
auto it = find_if(scores.begin(), scores.end(),
[&courseId](const Score& s) { return s.getCourseId() == courseId; });
if (it != scores.end()) {
scores.erase(it);
cout << "成绩已删除" << endl;
return true;
}
cout << "未找到该课程成绩" << endl;
return false;
}
double getAverageScore() const {
if (scores.empty()) return 0.0;
double sum = 0.0;
for (const auto& s : scores) {
sum += s.getScore();
}
return sum / scores.size();
}
double getTotalScore() const {
double sum = 0.0;
for (const auto& s : scores) {
sum += s.getScore();
}
return sum;
}
int getCourseCount() const {
return scores.size();
}
// 获取最高分
double getMaxScore() const {
if (scores.empty()) return 0.0;
double maxScore = scores[0].getScore();
for (const auto& s : scores) {
if (s.getScore() > maxScore) {
maxScore = s.getScore();
}
}
return maxScore;
}
// 获取最低分
double getMinScore() const {
if (scores.empty()) return 0.0;
double minScore = scores[0].getScore();
for (const auto& s : scores) {
if (s.getScore() < minScore) {
minScore = s.getScore();
}
}
return minScore;
}
// 显示学生基本信息
void displayBasic() const {
cout << left << setw(12) << stuId
<< setw(12) << name
<< setw(6) << gender
<< setw(6) << age
<< setw(15) << className
<< setw(15) << phone
<< setw(25) << email << endl;
}
// 显示学生详细信息
void displayDetail() const {
cout << "\n================== 学生详细信息 ==================" << endl;
cout << "学号: " << stuId << endl;
cout << "姓名: " << name << endl;
cout << "性别: " << gender << endl;
cout << "年龄: " << age << endl;
cout << "班级: " << className << endl;
cout << "电话: " << (phone.empty() ? "未填写" : phone) << endl;
cout << "邮箱: " << (email.empty() ? "未填写" : email) << endl;
cout << "地址: " << (address.empty() ? "未填写" : address) << endl;
cout << "================== 成绩信息 ==================" << endl;
if (scores.empty()) {
cout << "暂无成绩记录" << endl;
} else {
cout << left << setw(12) << "课程编号"
<< setw(10) << "分数"
<< setw(10) << "等级"
<< setw(20) << "考试时间" << endl;
cout << string(52, '-') << endl;
for (const auto& s : scores) {
s.display();
}
cout << string(52, '-') << endl;
cout << "平均分: " << fixed << setprecision(2) << getAverageScore() << endl;
cout << "总分: " << getTotalScore() << endl;
cout << "最高分: " << getMaxScore() << endl;
cout << "最低分: " << getMinScore() << endl;
cout << "修读课程数: " << getCourseCount() << endl;
}
cout << "==================================================" << endl;
}
// 成绩表显示
void displayScoreTable() const {
cout << name << "(" << stuId << ") 成绩单:" << endl;
cout << left << setw(20) << "课程名称"
<< setw(10) << "分数"
<< setw(10) << "等级" << endl;
cout << string(40, '-') << endl;
// 实际使用时需要关联课程名称,这里简化
for (const auto& s : scores) {
cout << left << setw(20) << s.getCourseId()
<< setw(10) << fixed << setprecision(1) << s.getScore()
<< setw(10) << s.getGrade() << endl;
}
}
// 获取成绩等级描述
string getGradeLevel() const {
double avg = getAverageScore();
if (avg >= 90) return "优秀";
else if (avg >= 80) return "良好";
else if (avg >= 70) return "中等";
else if (avg >= 60) return "及格";
else return "不及格";
}
// 比较运算符(用于排序)
bool operator<(const Student& other) const {
return getAverageScore() < other.getAverageScore();
}
bool operator>(const Student& other) const {
return getAverageScore() > other.getAverageScore();
}
bool operator==(const Student& other) const {
return stuId == other.stuId;
}
// 序列化
string serialize() const {
stringstream ss;
ss << stuId << "|" << name << "|" << gender << "|" << age << "|"
<< className << "|" << phone << "|" << email << "|" << address << "|";
// 序列化成绩
ss << scores.size() << "|";
for (const auto& score : scores) {
ss << score.serialize() << "|";
}
return ss.str();
}
// 反序列化
static Student deserialize(const string& data) {
stringstream ss(data);
string id, name, gender, ageStr, className, phone, email, address;
string scoreCountStr;
getline(ss, id, '|');
getline(ss, name, '|');
getline(ss, gender, '|');
getline(ss, ageStr, '|');
getline(ss, className, '|');
getline(ss, phone, '|');
getline(ss, email, '|');
getline(ss, address, '|');
getline(ss, scoreCountStr, '|');
Student stu(id, name, gender, stoi(ageStr), className, phone, email, address);
int scoreCount = stoi(scoreCountStr);
for (int i = 0; i < scoreCount; i++) {
string scoreData;
getline(ss, scoreData, '|');
if (!scoreData.empty()) {
stu.scores.push_back(Score::deserialize(scoreData));
}
}
return stu;
}
static int getTotalStudents() { return totalStudents; }
static void resetTotalStudents() { totalStudents = 0; }
};
int Student::totalStudents = 0;
// ====================== 课程管理类 ======================
class CourseManager {
private:
vector<Course> courses;
static CourseManager* instance;
string dataFile;
CourseManager() : dataFile("courses.dat") {
loadFromFile();
}
public:
static CourseManager& getInstance() {
if (instance == nullptr) {
instance = new CourseManager();
}
return *instance;
}
static void cleanup() {
delete instance;
instance = nullptr;
}
// 添加课程
bool addCourse(const Course& course) {
if (findCourse(course.getCourseId()) != -1) {
cout << "课程编号已存在!" << endl;
return false;
}
courses.push_back(course);
saveToFile();
cout << "课程添加成功" << endl;
return true;
}
// 查找课程索引
int findCourse(const string& courseId) const {
for (size_t i = 0; i < courses.size(); i++) {
if (courses[i].getCourseId() == courseId) {
return i;
}
}
return -1;
}
// 获取课程
Course* getCourse(const string& courseId) {
int idx = findCourse(courseId);
if (idx != -1) {
return &courses[idx];
}
return nullptr;
}
const Course* getCourse(const string& courseId) const {
int idx = findCourse(courseId);
if (idx != -1) {
return &courses[idx];
}
return nullptr;
}
// 更新课程
bool updateCourse(const string& courseId, const Course& newCourse) {
int idx = findCourse(courseId);
if (idx == -1) {
cout << "课程不存在!" << endl;
return false;
}
courses[idx] = newCourse;
saveToFile();
cout << "课程信息已更新" << endl;
return true;
}
// 删除课程
bool removeCourse(const string& courseId) {
int idx = findCourse(courseId);
if (idx == -1) {
cout << "课程不存在!" << endl;
return false;
}
courses.erase(courses.begin() + idx);
saveToFile();
cout << "课程已删除" << endl;
return true;
}
// 显示所有课程
void displayAllCourses() const {
if (courses.empty()) {
cout << "暂无课程信息" << endl;
return;
}
cout << "\n================== 课程列表 ==================" << endl;
cout << left << setw(12) << "课程编号"
<< setw(20) << "课程名称"
<< setw(8) << "学分"
<< setw(8) << "学时" << endl;
cout << string(48, '-') << endl;
for (const auto& course : courses) {
course.display();
}
cout << "==============================================" << endl;
}
// 搜索课程
void searchCourse(const string& keyword) const {
bool found = false;
cout << "\n================== 搜索结果 ==================" << endl;
cout << left << setw(12) << "课程编号"
<< setw(20) << "课程名称"
<< setw(8) << "学分"
<< setw(8) << "学时" << endl;
cout << string(48, '-') << endl;
for (const auto& course : courses) {
if (course.getCourseId().find(keyword) != string::npos ||
course.getCourseName().find(keyword) != string::npos) {
course.display();
found = true;
}
}
if (!found) {
cout << "未找到相关课程" << endl;
}
}
// 文件操作
void saveToFile() const {
ofstream file(dataFile);
if (!file.is_open()) {
cout << "无法打开文件保存课程数据" << endl;
return;
}
for (const auto& course : courses) {
file << course.serialize() << endl;
}
file.close();
}
void loadFromFile() {
courses.clear();
ifstream file(dataFile);
if (!file.is_open()) {
return;
}
string line;
while (getline(file, line)) {
if (!line.empty()) {
courses.push_back(Course::deserialize(line));
}
}
file.close();
}
size_t getCourseCount() const { return courses.size(); }
};
CourseManager* CourseManager::instance = nullptr;
// ====================== 学生管理类 ======================
class StudentManager {
private:
vector<Student> students;
string dataFile;
public:
StudentManager() : dataFile("students.dat") {
loadFromFile();
}
~StudentManager() {
saveToFile();
}
// ========== 增删改查 ==========
// 添加学生
bool addStudent(const Student& student) {
if (findStudent(student.getStuId()) != -1) {
cout << "学号已存在!" << endl;
return false;
}
students.push_back(student);
saveToFile();
cout << "学生添加成功" << endl;
return true;
}
// 查找学生索引
int findStudent(const string& stuId) const {
for (size_t i = 0; i < students.size(); i++) {
if (students[i].getStuId() == stuId) {
return i;
}
}
return -1;
}
// 获取学生
Student* getStudent(const string& stuId) {
int idx = findStudent(stuId);
if (idx != -1) {
return &students[idx];
}
return nullptr;
}
// 更新学生信息
bool updateStudent(const string& stuId, const Student& newStudent) {
int idx = findStudent(stuId);
if (idx == -1) {
cout << "学生不存在!" << endl;
return false;
}
students[idx] = newStudent;
saveToFile();
cout << "学生信息已更新" << endl;
return true;
}
// 删除学生
bool removeStudent(const string& stuId) {
int idx = findStudent(stuId);
if (idx == -1) {
cout << "学生不存在!" << endl;
return false;
}
students.erase(students.begin() + idx);
saveToFile();
cout << "学生已删除" << endl;
return true;
}
// ========== 成绩管理 ==========
// 添加成绩
bool addScore(const string& stuId, const Score& score) {
int idx = findStudent(stuId);
if (idx == -1) {
cout << "学生不存在!" << endl;
return false;
}
// 验证课程是否存在
if (CourseManager::getInstance().getCourse(score.getCourseId()) == nullptr) {
cout << "课程不存在!请先添加课程" << endl;
return false;
}
students[idx].addScore(score);
saveToFile();
return true;
}
// 删除成绩
bool removeScore(const string& stuId, const string& courseId) {
int idx = findStudent(stuId);
if (idx == -1) {
cout << "学生不存在!" << endl;
return false;
}
bool result = students[idx].removeScore(courseId);
if (result) {
saveToFile();
}
return result;
}
// ========== 查询显示 ==========
// 显示所有学生(简要信息)
void displayAllStudents() const {
if (students.empty()) {
cout << "暂无学生信息" << endl;
return;
}
cout << "\n================== 学生列表 ==================" << endl;
cout << left << setw(12) << "学号"
<< setw(12) << "姓名"
<< setw(6) << "性别"
<< setw(6) << "年龄"
<< setw(15) << "班级"
<< setw(15) << "电话"
<< setw(25) << "邮箱" << endl;
cout << string(91, '-') << endl;
for (const auto& student : students) {
student.displayBasic();
}
cout << "================================================" << endl;
cout << "总人数: " << students.size() << endl;
}
// 显示学生详细信息
void displayStudentDetail(const string& stuId) const {
int idx = findStudent(stuId);
if (idx == -1) {
cout << "学生不存在!" << endl;
return;
}
students[idx].displayDetail();
}
// 按班级显示学生
void displayByClass(const string& className) const {
bool found = false;
cout << "\n================== " << className << " 班学生列表 ==================" << endl;
cout << left << setw(12) << "学号"
<< setw(12) << "姓名"
<< setw(6) << "性别"
<< setw(6) << "年龄"
<< setw(10) << "平均分"
<< setw(8) << "等级" << endl;
cout << string(54, '-') << endl;
for (const auto& student : students) {
if (student.getClassName() == className) {
cout << left << setw(12) << student.getStuId()
<< setw(12) << student.getName()
<< setw(6) << student.getGender()
<< setw(6) << student.getAge()
<< setw(10) << fixed << setprecision(1) << student.getAverageScore()
<< setw(8) << student.getGradeLevel() << endl;
found = true;
}
}
if (!found) {
cout << "该班级暂无学生" << endl;
}
}
// 搜索学生
void searchStudent(const string& keyword) const {
bool found = false;
cout << "\n================== 搜索结果 ==================" << endl;
cout << left << setw(12) << "学号"
<< setw(12) << "姓名"
<< setw(6) << "性别"
<< setw(6) << "年龄"
<< setw(15) << "班级"
<< setw(10) << "平均分" << endl;
cout << string(61, '-') << endl;
for (const auto& student : students) {
if (student.getStuId().find(keyword) != string::npos ||
student.getName().find(keyword) != string::npos) {
cout << left << setw(12) << student.getStuId()
<< setw(12) << student.getName()
<< setw(6) << student.getGender()
<< setw(6) << student.getAge()
<< setw(15) << student.getClassName()
<< setw(10) << fixed << setprecision(1) << student.getAverageScore() << endl;
found = true;
}
}
if (!found) {
cout << "未找到相关学生" << endl;
}
}
// ========== 排序功能 ==========
// 按学号排序
void sortByStuId() {
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.getStuId() < b.getStuId();
});
cout << "已按学号排序" << endl;
}
// 按姓名排序
void sortByName() {
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.getName() < b.getName();
});
cout << "已按姓名排序" << endl;
}
// 按平均分排序
void sortByAverage(bool descending = true) {
if (descending) {
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.getAverageScore() > b.getAverageScore();
});
cout << "已按平均分降序排序" << endl;
} else {
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.getAverageScore() < b.getAverageScore();
});
cout << "已按平均分升序排序" << endl;
}
}
// ========== 统计分析 ==========
// 成绩统计分析
void gradeStatistics() const {
if (students.empty()) {
cout << "暂无学生数据" << endl;
return;
}
map<string, int> gradeDistribution;
double totalAvg = 0.0;
int studentCount = 0;
for (const auto& student : students) {
if (student.getCourseCount() > 0) {
totalAvg += student.getAverageScore();
studentCount++;
gradeDistribution[student.getGradeLevel()]++;
}
}
cout << "\n================== 成绩统计分析 ==================" << endl;
cout << "参与统计学生数: " << studentCount << endl;
cout << "全校平均分: " << fixed << setprecision(2)
<< (studentCount > 0 ? totalAvg / studentCount : 0) << endl;
cout << "\n等级分布:" << endl;
cout << left << setw(10) << "等级" << setw(10) << "人数" << setw(10) << "占比" << endl;
cout << string(30, '-') << endl;
for (const auto& pair : gradeDistribution) {
double percent = (double)pair.second / studentCount * 100;
cout << left << setw(10) << pair.first
<< setw(10) << pair.second
<< setw(10) << fixed << setprecision(1) << percent << "%" << endl;
}
cout << "==================================================" << endl;
}
// 班级排名
void classRanking(const string& className) const {
vector<pair<string, double>> classScores;
for (const auto& student : students) {
if (student.getClassName() == className && student.getCourseCount() > 0) {
classScores.push_back({student.getName(), student.getAverageScore()});
}
}
if (classScores.empty()) {
cout << "该班级暂无成绩数据" << endl;
return;
}
sort(classScores.begin(), classScores.end(),
[](const pair<string, double>& a, const pair<string, double>& b) {
return a.second > b.second;
});
cout << "\n================== " << className << " 班成绩排名 ==================" << endl;
cout << left << setw(8) << "名次"
<< setw(12) << "姓名"
<< setw(10) << "平均分" << endl;
cout << string(30, '-') << endl;
for (size_t i = 0; i < classScores.size(); i++) {
cout << left << setw(8) << (i + 1)
<< setw(12) << classScores[i].first
<< setw(10) << fixed << setprecision(1) << classScores[i].second << endl;
}
}
// ========== 文件操作 ==========
void saveToFile() const {
ofstream file(dataFile);
if (!file.is_open()) {
cout << "无法打开文件保存学生数据" << endl;
return;
}
for (const auto& student : students) {
file << student.serialize() << endl;
}
file.close();
}
void loadFromFile() {
students.clear();
Student::resetTotalStudents();
ifstream file(dataFile);
if (!file.is_open()) {
return;
}
string line;
while (getline(file, line)) {
if (!line.empty()) {
students.push_back(Student::deserialize(line));
}
}
file.close();
}
size_t getStudentCount() const { return students.size(); }
// 获取所有班级列表
vector<string> getAllClasses() const {
vector<string> classes;
for (const auto& student : students) {
string className = student.getClassName();
if (find(classes.begin(), classes.end(), className) == classes.end()) {
classes.push_back(className);
}
}
return classes;
}
};
// ====================== 菜单系统 ======================
class MenuSystem {
private:
StudentManager studentManager;
CourseManager& courseManager;
void clearScreen() {
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
}
void pause() {
cout << "\n按回车键继续...";
cin.ignore();
cin.get();
}
void showMainMenu() {
cout << "\n";
cout << "╔══════════════════════════════════════════════════════════╗\n";
cout << "║ 学生信息管理系统 ║\n";
cout = "╠══════════════════════════════════════════════════════════╣\n";
cout << "║ 1. 学生管理 ║\n";
cout << "║ 2. 课程管理 ║\n";
cout << "║ 3. 成绩管理 ║\n";
cout << "║ 4. 查询统计 ║\n";
cout << "║ 5. 数据排序 ║\n";
cout << "║ 0. 退出系统 ║\n";
cout << "╚══════════════════════════════════════════════════════════╝\n";
cout << "请选择操作: ";
}
void showStudentMenu() {
cout << "\n";
cout << "╔════════════════════════════════════════╗\n";
cout << "║ 学生管理子菜单 ║\n";
cout << "╠════════════════════════════════════════╣\n";
cout << "║ 1. 添加学生 ║\n";
cout << "║ 2. 修改学生信息 ║\n";
cout << "║ 3. 删除学生 ║\n";
cout << "║ 4. 查看所有学生 ║\n";
cout << "║ 5. 查看学生详细信息 ║\n";
cout << "║ 6. 按班级查看学生 ║\n";
cout << "║ 0. 返回主菜单 ║\n";
cout << "╚════════════════════════════════════════╝\n";
cout << "请选择操作: ";
}
void showCourseMenu() {
cout << "\n";
cout << "╔════════════════════════════════════════╗\n";
cout << "║ 课程管理子菜单 ║\n";
cout << "╠════════════════════════════════════════╣\n";
cout << "║ 1. 添加课程 ║\n";
cout << "║ 2. 修改课程信息 ║\n";
cout << "║ 3. 删除课程 ║\n";
cout << "║ 4. 查看所有课程 ║\n";
cout << "║ 5. 搜索课程 ║\n";
cout << "║ 0. 返回主菜单 ║\n";
cout << "╚════════════════════════════════════════╝\n";
cout << "请选择操作: ";
}
void showScoreMenu() {
cout << "\n";
cout << "╔════════════════════════════════════════╗\n";
cout << "║ 成绩管理子菜单 ║\n";
cout << "╠════════════════════════════════════════╣\n";
cout << "║ 1. 添加/修改成绩 ║\n";
cout << "║ 2. 删除成绩 ║\n";
cout << "║ 3. 查看学生成绩单 ║\n";
cout << "║ 0. 返回主菜单 ║\n";
cout << "╚════════════════════════════════════════╝\n";
cout << "请选择操作: ";
}
void showQueryMenu() {
cout << "\n";
cout << "╔════════════════════════════════════════╗\n";
cout << "║ 查询统计子菜单 ║\n";
cout << "╠════════════════════════════════════════╣\n";
cout << "║ 1. 搜索学生(学号/姓名) ║\n";
cout << "║ 2. 成绩统计分析 ║\n";
cout << "║ 3. 班级成绩排名 ║\n";
cout << "║ 0. 返回主菜单 ║\n";
cout << "╚════════════════════════════════════════╝\n";
cout << "请选择操作: ";
}
void showSortMenu() {
cout << "\n";
cout << "╔════════════════════════════════════════╗\n";
cout << "║ 排序子菜单 ║\n";
cout << "╠════════════════════════════════════════╣\n";
cout << "║ 1. 按学号排序 ║\n";
cout << "║ 2. 按姓名排序 ║\n";
cout << "║ 3. 按平均分降序排序 ║\n";
cout << "║ 4. 按平均分升序排序 ║\n";
cout << "║ 0. 返回主菜单 ║\n";
cout << "╚════════════════════════════════════════╝\n";
cout << "请选择操作: ";
}
public:
MenuSystem() : courseManager(CourseManager::getInstance()) {}
void run() {
int choice;
do {
showMainMenu();
cin >> choice;
switch (choice) {
case 1:
studentManagement();
break;
case 2:
courseManagement();
break;
case 3:
scoreManagement();
break;
case 4:
queryAndStatistic();
break;
case 5:
sortManagement();
break;
case 0:
cout << "感谢使用学生信息管理系统,再见!" << endl;
break;
default:
cout << "无效选择,请重新输入!" << endl;
pause();
}
} while (choice != 0);
}
void studentManagement() {
int choice;
do {
showStudentMenu();
cin >> choice;
switch (choice) {
case 1: {
string id, name, gender, className, phone, email, address;
int age;
cout << "请输入学号: ";
cin >> id;
cout << "请输入姓名: ";
cin >> name;
cout << "请输入性别(男/女): ";
cin >> gender;
cout << "请输入年龄: ";
cin >> age;
cout << "请输入班级: ";
cin >> className;
cout << "请输入电话: ";
cin >> phone;
cout << "请输入邮箱: ";
cin >> email;
cout << "请输入地址: ";
cin.ignore();
getline(cin, address);
Student stu(id, name, gender, age, className, phone, email, address);
studentManager.addStudent(stu);
pause();
break;
}
case 2: {
string id;
cout << "请输入要修改的学生学号: ";
cin >> id;
Student* stu = studentManager.getStudent(id);
if (stu) {
string name, gender, className, phone, email, address;
int age;
cout << "当前信息 - 姓名: " << stu->getName() << endl;
cout << "请输入新姓名(直接回车保留原值): ";
cin.ignore();
getline(cin, name);
if (!name.empty()) stu->setName(name);
cout << "当前性别: " << stu->getGender() << endl;
cout << "请输入新性别: ";
getline(cin, gender);
if (!gender.empty()) stu->setGender(gender);
cout << "当前年龄: " << stu->getAge() << endl;
cout << "请输入新年龄: ";
string ageStr;
getline(cin, ageStr);
if (!ageStr.empty()) stu->setAge(stoi(ageStr));
cout << "当前班级: " << stu->getClassName() << endl;
cout << "请输入新班级: ";
getline(cin, className);
if (!className.empty()) stu->setClassName(className);
cout << "当前电话: " << stu->getPhone() << endl;
cout << "请输入新电话: ";
getline(cin, phone);
if (!phone.empty()) stu->setPhone(phone);
cout << "当前邮箱: " << stu->getEmail() << endl;
cout << "请输入新邮箱: ";
getline(cin, email);
if (!email.empty()) stu->setEmail(email);
cout << "当前地址: " << stu->getAddress() << endl;
cout << "请输入新地址: ";
getline(cin, address);
if (!address.empty()) stu->setAddress(address);
studentManager.updateStudent(id, *stu);
} else {
cout << "学生不存在!" << endl;
}
pause();
break;
}
case 3: {
string id;
cout << "请输入要删除的学生学号: ";
cin >> id;
studentManager.removeStudent(id);
pause();
break;
}
case 4:
studentManager.displayAllStudents();
pause();
break;
case 5: {
string id;
cout << "请输入学生学号: ";
cin >> id;
studentManager.displayStudentDetail(id);
pause();
break;
}
case 6: {
string className;
cout << "请输入班级名称: ";
cin >> className;
studentManager.displayByClass(className);
pause();
break;
}
}
} while (choice != 0);
}
void courseManagement() {
int choice;
do {
showCourseMenu();
cin >> choice;
switch (choice) {
case 1: {
string id, name;
int credit, hours;
cout << "请输入课程编号: ";
cin >> id;
cout << "请输入课程名称: ";
cin >> name;
cout << "请输入学分: ";
cin >> credit;
cout << "请输入学时: ";
cin >> hours;
Course course(id, name, credit, hours);
courseManager.addCourse(course);
pause();
break;
}
case 2: {
string id;
cout << "请输入要修改的课程编号: ";
cin >> id;
Course* course = courseManager.getCourse(id);
if (course) {
string name;
int credit, hours;
cout << "当前课程名: " << course->getCourseName() << endl;
cout << "请输入新课程名: ";
cin >> name;
if (!name.empty()) course->setCourseName(name);
cout << "当前学分: " << course->getCredit() << endl;
cout << "请输入新学分: ";
string creditStr;
cin >> creditStr;
if (!creditStr.empty()) course->setCredit(stoi(creditStr));
cout << "当前学时: " << course->getHours() << endl;
cout << "请输入新学时: ";
string hoursStr;
cin >> hoursStr;
if (!hoursStr.empty()) course->setHours(stoi(hoursStr));
courseManager.updateCourse(id, *course);
} else {
cout << "课程不存在!" << endl;
}
pause();
break;
}
case 3: {
string id;
cout << "请输入要删除的课程编号: ";
cin >> id;
courseManager.removeCourse(id);
pause();
break;
}
case 4:
courseManager.displayAllCourses();
pause();
break;
case 5: {
string keyword;
cout << "请输入搜索关键词: ";
cin >> keyword;
courseManager.searchCourse(keyword);
pause();
break;
}
}
} while (choice != 0);
}
void scoreManagement() {
int choice;
do {
showScoreMenu();
cin >> choice;
switch (choice) {
case 1: {
string stuId, courseId, examTime;
double score;
cout << "请输入学生学号: ";
cin >> stuId;
cout << "请输入课程编号: ";
cin >> courseId;
cout << "请输入成绩: ";
cin >> score;
cout << "请输入考试时间(格式: YYYY-MM-DD): ";
cin >> examTime;
Score sc(courseId, score, examTime);
studentManager.addScore(stuId, sc);
pause();
break;
}
case 2: {
string stuId, courseId;
cout << "请输入学生学号: ";
cin >> stuId;
cout << "请输入课程编号: ";
cin >> courseId;
studentManager.removeScore(stuId, courseId);
pause();
break;
}
case 3: {
string stuId;
cout << "请输入学生学号: ";
cin >> stuId;
studentManager.displayStudentDetail(stuId);
pause();
break;
}
}
} while (choice != 0);
}
void queryAndStatistic() {
int choice;
do {
showQueryMenu();
cin >> choice;
switch (choice) {
case 1: {
string keyword;
cout << "请输入搜索关键词(学号/姓名): ";
cin >> keyword;
studentManager.searchStudent(keyword);
pause();
break;
}
case 2:
studentManager.gradeStatistics();
pause();
break;
case 3: {
string className;
cout << "请输入班级名称: ";
cin >> className;
studentManager.classRanking(className);
pause();
break;
}
}
} while (choice != 0);
}
void sortManagement() {
int choice;
do {
showSortMenu();
cin >> choice;
switch (choice) {
case 1:
studentManager.sortByStuId();
studentManager.displayAllStudents();
pause();
break;
case 2:
studentManager.sortByName();
studentManager.displayAllStudents();
pause();
break;
case 3:
studentManager.sortByAverage(true);
studentManager.displayAllStudents();
pause();
break;
case 4:
studentManager.sortByAverage(false);
studentManager.displayAllStudents();
pause();
break;
}
} while (choice != 0);
}
};
// ====================== 主函数 ======================
int main() {
cout << "╔══════════════════════════════════════════════════════════════╗\n";
cout << "║ ║\n";
cout << "║ 欢迎使用学生信息管理系统 V2.0 ║\n";
cout << "║ ║\n";
cout << "║ 瑶池酒剑仙 出品 ║\n";
cout << "║ ║\n";
cout << "╚══════════════════════════════════════════════════════════════╝\n";
MenuSystem menu;
menu.run();
CourseManager::cleanup();
return 0;
}

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!
🌲 请进入下一专栏: 项目实战合集
🌲 彩蛋壁纸别忘了先看哈!


新壁纸(雨夜论道)

墨智:今日有无根水降,这洼地之水,便是生,他日无根水失,这洼地之水,便是死,没有了生机,没有了流通,所谓死水,便是如此!
今日,他们可喜、可怒、可哀、可乐,便是生,他日,他们不会喜怒哀乐,难逃轮回,便是死。
此庙宇神像在时,庙宇为生,如今神像消失,便是死!
这雨,出生于天,死于大地,中间的过程,便是人生,我之所以看这雨水,不看天,不看地,看的也不是雨,而是这雨的一生......这便是生与死!