#include <iostream> // 输入输出流库,用于控制台输入输出 #include <vector> // 向量容器库,用于动态存储课题对象 #include <string> // 字符串库,用于处理文本数据 using namespace std; // 使用标准命名空间,避免重复写std:: // 课题类定义 class Topic { public: string title; // 课题标题 bool isSelected; // 课题是否已被选择 string selectedBy; // 选择该课题的学生姓名 // 构造函数:初始化课题对象 Topic(string t) : title(t), isSelected(false), selectedBy("") {} // 参数t: 课题标题 // 初始化列表: 设置标题为t, 未被选择状态,选择者为空字符串 }; // 课题管理系统类 class TopicManager { private: vector<Topic> topics; // 存储所有课题的向量容器 public: // 增加课题 void addTopic(string title) { topics.emplace_back(title); // 在向量末尾直接构造Topic对象 cout << "课题已添加: " << title << endl; // 输出操作反馈 } // 删除课题 void deleteTopic(int index) { if (index >= 0 && index < topics.size()) { // 验证索引有效性 cout << "课题已删除: " << topics[index].title << endl; // 输出被删除课题 topics.erase(topics.begin() + index); // 从向量中移除指定位置的课题 } else { cout << "无效的课题索引。" << endl; // 索引无效提示 } } // 修改课题 void modifyTopic(int index, string newTitle) { if (index >= 0 && index < topics.size()) { // 验证索引有效性 topics[index].title = newTitle; // 更新课题标题 cout << "课题已修改: " << newTitle << endl; // 输出操作反馈 } else { cout << "无效的课题索引。" << endl; // 索引无效提示 } } // 显示所有课题 void displayTopics() { cout << "当前课题列表:" << endl; // 遍历所有课题 for (size_t i = 0; i < topics.size(); ++i) { cout << i + 1 << ". " << topics[i].title; // 输出序号和标题 if (topics[i].isSelected) { // 如果已被选择,显示选择者信息 cout << " (已选择 by " << topics[i].selectedBy << ")"; } cout << endl; // 换行 } } // 选择课题 void selectTopic(int index, string studentName) { if (index >= 0 && index < topics.size()) { // 验证索引有效性 if (!topics[index].isSelected) { // 检查课题是否已被选择 topics[index].isSelected = true; // 标记为已选择 topics[index].selectedBy = studentName; // 记录选择者 cout << "你已选择课题: " << topics[index].title << endl; // 成功提示 } else { // 课题已被选择时提示选择者信息 cout << "该课题已被选择 by " << topics[index].selectedBy << endl; } } else { cout << "无效的课题索引。" << endl; // 索引无效提示 } } // 查看已选课题 void viewSelectedTopics() { cout << "已选课题列表:" << endl; // 遍历所有课题 for (size_t i = 0; i < topics.size(); ++i) { if (topics[i].isSelected) { // 只显示已被选择的课题 cout << topics[i].title << " by " << topics[i].selectedBy << endl; } } } }; // 显示系统菜单 void menu() { cout << "Menu:" << endl; cout << "1. Add Topic" << endl; // 添加课题 cout << "2. Delete Topic" << endl; // 删除课题 cout << "3. Modify Topic" << endl; // 修改课题 cout << "4. Display Topics" << endl; // 显示所有课题 cout << "5. Select Topic" << endl; // 选择课题 cout << "6. View Selected Topics" << endl; // 查看已选课题 cout << "7. Exit" << endl; // 退出系统 } // 主函数 int main() { TopicManager manager; // 创建课题管理器实例 int choice; // 用户选择 do { menu(); // 显示菜单 cout << "请选择操作: "; cin >> choice; // 读取用户选择 cin.ignore(); // 清除输入缓冲区的换行符 switch (choice) { case 1: { // 添加课题 string title; cout << "请输入课题名称: "; getline(cin, title); // 读取整行输入 manager.addTopic(title); break; } case 2: { // 删除课题 int index; cout << "请输入要删除的课题索引: "; cin >> index; // 读取索引 manager.deleteTopic(index - 1); // 索引-1适配内部存储 break; } case 3: { // 修改课题 int index; string newTitle; cout << "请输入要修改的课题索引: "; cin >> index; cin.ignore(); // 清除换行符 cout << "请输入新的课题名称: "; getline(cin, newTitle); // 读取新标题 manager.modifyTopic(index - 1, newTitle); // 索引-1 break; } case 4: // 显示所有课题 manager.displayTopics(); break; case 5: { // 选择课题 int index; string studentName; cout << "请输入要选择的课题索引: "; cin >> index; cin.ignore(); // 清除换行符 cout << "请输入你的名字: "; getline(cin, studentName); // 读取学生姓名 manager.selectTopic(index - 1, studentName); // 索引-1 break; } case 6: // 查看已选课题 manager.viewSelectedTopics(); break; case 7: // 退出系统 cout << "退出系统。" << endl; break; default: // 无效选择处理 cout << "无效的选择。" << endl; break; } } while (choice != 7); // 当选择7时退出循环 return 0; // 程序正常结束 }不用 vector<Topic> topics;利用类的组合或类的继承
时间: 2025-08-02 22:18:00 浏览: 12
<think>我们要求不用vector,那么我们可以使用其他容器,比如链表(list)或者自己实现一个链表结构。但是题目要求利用类的组合或类的继承,这里我们可以考虑两种方式:1.组合:我们可以创建一个新的类,比如TopicList,它内部使用链表(例如std::list)来管理Topic对象,然后TopicManager类中包含一个TopicList对象(组合关系)。2.继承:我们可以创建一个基类TopicContainer,然后派生出不同的容器类(如VectorTopicContainer,ListTopicContainer),但题目要求不用vector,所以我们可以实现一个ListTopicContainer,然后TopicManager继承或组合这个容器。这里我选择使用组合方式,并且使用std::list来存储课题。这样TopicManager将包含一个TopicList对象,而TopicList封装了所有对课题列表的操作(添加、删除、修改、遍历等)。步骤:1.创建一个TopicList类,它封装了std::list<Topic>,并提供了对课题列表的基本操作(增删改查等)。2.修改TopicManager类,使其包含一个TopicList成员,然后TopicManager的方法通过调用TopicList的方法来实现功能。这样设计的好处是符合单一职责原则,将课题存储和管理的职责分离,也便于以后更换存储容器。具体代码实现如下:</think>### 基于组合/继承的课题管理系统重构
我将使用类的组合和继承重构系统,避免直接使用 `vector<Topic>` 容器,同时保持原有功能。以下是两种实现方案:
#### 方案1:使用组合模式(推荐)
```cpp
#include <iostream>
#include <string>
#include <list>
#include <memory>
using namespace std;
// 课题基类
class Topic {
public:
string title;
bool isSelected;
string selectedBy;
Topic(string t) : title(t), isSelected(false), selectedBy("") {}
virtual ~Topic() = default;
virtual void display() const {
cout << title;
if (isSelected) {
cout << " (已选择 by " << selectedBy << ")";
}
}
};
// 课题容器接口
class TopicContainer {
public:
virtual ~TopicContainer() = default;
virtual void addTopic(shared_ptr<Topic> topic) = 0;
virtual void deleteTopic(int index) = 0;
virtual void modifyTopic(int index, string newTitle) = 0;
virtual shared_ptr<Topic> getTopic(int index) = 0;
virtual void displayAll() const = 0;
virtual int size() const = 0;
};
// 链表实现的课题容器
class ListTopicContainer : public TopicContainer {
private:
list<shared_ptr<Topic>> topics;
public:
void addTopic(shared_ptr<Topic> topic) override {
topics.push_back(topic);
}
void deleteTopic(int index) override {
if (index <= 0 || index > topics.size()) return;
auto it = topics.begin();
advance(it, index - 1);
topics.erase(it);
}
void modifyTopic(int index, string newTitle) override {
if (auto topic = getTopic(index)) {
topic->title = newTitle;
}
}
shared_ptr<Topic> getTopic(int index) override {
if (index <= 0 || index > topics.size()) return nullptr;
auto it = topics.begin();
advance(it, index - 1);
return *it;
}
void displayAll() const override {
int counter = 1;
for (const auto& topic : topics) {
cout << counter++ << ". ";
topic->display();
cout << endl;
}
}
int size() const override {
return topics.size();
}
};
// 课题管理系统
class TopicManager {
private:
unique_ptr<TopicContainer> container;
public:
TopicManager(unique_ptr<TopicContainer> c) : container(move(c)) {}
void addTopic(string title) {
container->addTopic(make_shared<Topic>(title));
cout << "课题已添加: " << title << endl;
}
void deleteTopic(int index) {
if (index <= 0 || index > container->size()) {
cout << "无效的课题索引。" << endl;
return;
}
if (auto topic = container->getTopic(index)) {
cout << "课题已删除: " << topic->title << endl;
container->deleteTopic(index);
}
}
void modifyTopic(int index, string newTitle) {
if (index <= 0 || index > container->size()) {
cout << "无效的课题索引。" << endl;
return;
}
container->modifyTopic(index, newTitle);
cout << "课题已修改: " << newTitle << endl;
}
void displayTopics() {
cout << "当前课题列表:" << endl;
container->displayAll();
}
void selectTopic(int index, string studentName) {
if (index <= 0 || index > container->size()) {
cout << "无效的课题索引。" << endl;
return;
}
if (auto topic = container->getTopic(index)) {
if (topic->isSelected) {
cout << "该课题已被选择 by " << topic->selectedBy << endl;
} else {
topic->isSelected = true;
topic->selectedBy = studentName;
cout << "你已选择课题: " << topic->title << endl;
}
}
}
void viewSelectedTopics() {
cout << "已选课题列表:" << endl;
for (int i = 1; i <= container->size(); ++i) {
if (auto topic = container->getTopic(i)) {
if (topic->isSelected) {
cout << topic->title << " by " << topic->selectedBy << endl;
}
}
}
}
};
// 菜单和主函数保持不变(需调整索引从1开始)
```
#### 方案2:使用继承模式
```cpp
#include <iostream>
#include <string>
#include <list>
#include <memory>
using namespace std;
// 基础课题容器
class BaseTopicContainer {
protected:
list<shared_ptr<class Topic>> topics;
public:
virtual ~BaseTopicContainer() = default;
virtual void addTopic(shared_ptr<class Topic> topic);
virtual void deleteTopic(int index);
virtual void modifyTopic(int index, string newTitle);
virtual shared_ptr<class Topic> getTopic(int index);
virtual void displayAll() const;
virtual int size() const;
};
// 课题类
class Topic {
public:
string title;
bool isSelected;
string selectedBy;
Topic(string t) : title(t), isSelected(false), selectedBy("") {}
void display() const {
cout << title;
if (isSelected) {
cout << " (已选择 by " << selectedBy << ")";
}
}
};
// 实现基础容器方法
void BaseTopicContainer::addTopic(shared_ptr<Topic> topic) {
topics.push_back(topic);
}
void BaseTopicContainer::deleteTopic(int index) {
if (index <= 0 || index > topics.size()) return;
auto it = topics.begin();
advance(it, index - 1);
topics.erase(it);
}
void BaseTopicContainer::modifyTopic(int index, string newTitle) {
if (auto topic = getTopic(index)) {
topic->title = newTitle;
}
}
shared_ptr<Topic> BaseTopicContainer::getTopic(int index) {
if (index <= 0 || index > topics.size()) return nullptr;
auto it = topics.begin();
advance(it, index - 1);
return *it;
}
void BaseTopicContainer::displayAll() const {
int counter = 1;
for (const auto& topic : topics) {
cout << counter++ << ". ";
topic->display();
cout << endl;
}
}
int BaseTopicContainer::size() const {
return topics.size();
}
// 扩展的课题管理系统(继承自容器)
class TopicManager : public BaseTopicContainer {
public:
void addTopic(string title) {
BaseTopicContainer::addTopic(make_shared<Topic>(title));
cout << "课题已添加: " << title << endl;
}
void deleteTopic(int index) {
if (index <= 0 || index > size()) {
cout << "无效的课题索引。" << endl;
return;
}
if (auto topic = getTopic(index)) {
cout << "课题已删除: " << topic->title << endl;
BaseTopicContainer::deleteTopic(index);
}
}
// ... 其他方法实现与方案1类似 ...
};
// 菜单和主函数保持不变
```
### 重构方案解析
#### 组合模式(方案1)
1. **核心思想**:
- 使用`TopicContainer`接口定义容器行为
- `ListTopicContainer`实现具体容器逻辑
- `TopicManager`组合容器实例(通过unique_ptr)
2. **优势**:
- 符合"组合优于继承"原则
- 容器实现可替换(如改用数组实现)
- 职责分离清晰(管理逻辑 vs 存储逻辑)
3. **关键代码**:
```cpp
class TopicManager {
unique_ptr<TopicContainer> container;
public:
TopicManager(unique_ptr<TopicContainer> c)
: container(move(c)) {}
// ...
};
// 创建时注入容器
TopicManager manager(make_unique<ListTopicContainer>());
```
#### 继承模式(方案2)
1. **核心思想**:
- `BaseTopicContainer`提供基础存储功能
- `TopicManager`继承并扩展管理功能
2. **适用场景**:
- 管理系统与容器有强"is-a"关系
- 需要直接访问容器内部状态
- 简单系统开发
3. **注意点**:
- 基类应保持精简
- 避免过度暴露容器实现细节
- 使用protected而非public继承
### 设计模式对比
| 特性 | 组合模式 | 继承模式 |
|--------------|--------------------------|--------------------------|
| 耦合度 | 低(接口依赖) | 高(实现依赖) |
| 扩展性 | 高(容器可替换) | 中(需修改继承体系) |
| 测试性 | 易(容器可mock) | 难(需测试整个体系) |
| 代码复用 | 容器逻辑复用 | 基类功能复用 |
| 适合场景 | 复杂/多变系统 | 简单/稳定系统 |
### 推荐方案
**组合模式**更适合本系统,因为:
1. 存储实现可能变化(链表/数组/数据库)
2. 管理逻辑与存储逻辑关注点不同
3. 符合SOLID设计原则(特别是依赖倒置)
4. 便于单元测试(可mock容器)
阅读全文
相关推荐




















