源代码:
#include <iostream>
#include <string>
#include <vector>
// 提前声明,因为Student类会用到Course类
class Student;
// 课程类
class Course {
private:
std::string name; // 课程名称
int credit; // 学分
std::vector<Student*> students; // 选课学生列表
public:
// 构造函数
Course(std::string n, int c) : name(n), credit(c) {}
// 选课方法
std::string enroll(Student* student);
// 获取课程名称(供Student类使用)
std::string getName() const { return name; }
// 获取学分(供Student类使用)
int getCredit() const { return credit; }
};
// 学生类
class Student {
private:
std::string name; // 姓名
int age; // 年龄
std::string sex; // 性别
int credit; // 总学分
public:
// 构造函数
Student(std::string n, int a, std::string s, int c)
: name(n), age(a), sex(s), credit(c) {}
// 选课方法
std::string takeCourse(Course* course);
// 获取姓名(供Course类使用)
std::string getName() const { return name; }
// 增加学分(供Course类使用)
void addCredit(int c) { credit += c; }
};
// 实现Course类的enroll方法
std::string Course::enroll(Student* student) {
students.push_back(student);
student->addCredit(credit);
return student->getName() + "已选课《" + name + "》";
}
// 实现Student类的takeCourse方法
std::string Student::takeCourse(Course* course) {
return course->enroll(this);
}
int main() {
// 创建课程对象
Course math("高等数学", 4);
// 创建学生对象
Student student("小明", 20, "男", 0);
// 学生选课
std::string result = student.takeCourse(&math);
// 输出结果
std::cout << result << std::endl;
return 0;
}
关键概念解析(新手必看)
-
类与对象
-
Course
和Student
是类(设计蓝图) -
math
,alice
是对象(具体实例) -
类比:类=汽车设计图,对象=实际制造的汽车
-
-
封装特性
private: // 隐藏内部实现 public: // 公开接口
-
数据(姓名/学分)设为private防止意外修改
-
通过public方法(如getName())安全访问
-
-
前向声明
class Student; // 告诉编译器"稍后定义"
-
解决循环依赖:Course需要知道Student存在
-
只能使用指针/引用(此时类未完全定义)
-
-
this指针
course->enroll(this); // 传递当前对象地址
-
每个成员函数内的隐藏参数
-
指向调用该方法的对象
-
-
vector容器
vector<Student*> students; // 动态数组
-
动态存储选课学生指针
-
自动管理内存,无需固定大小
-
-
const成员函数
string getName() const { ... }
-
承诺不修改对象状态
-
允许const对象调用:
const Student s(...); s.getName();
-
内存管理图解
+----------+ +----------+ | Course | | Student | | name | | name | | credit | | age | | students |----->| sex | +----------+ | credit | +----------+ ▲ ▲ | | | 存储指针 | 实际对象 | | +------+------+ +----+-----+ | vector | | main() | | [0]: &alice | | alice | | [1]: &bob | | bob | +-------------+ +----------+
常见问题解决
-
循环依赖问题
-
使用前向声明 + 指针/引用
-
避免相互包含头文件
-
-
重复选课检测
// 在Course::enroll中添加 for(auto s : students) { if(s == student) { return student->getName() + " already enrolled!"; } }
-
内存安全
-
当前版本使用栈对象(自动回收)
-
动态创建对象时需注意:
Student* s = new Student(...); // 必须配套 delete
-