实验4
一、实验任务1
源代码task1
1 #include <algorithm> 2 #include <array> 3 #include <cstdlib> 4 #include <iomanip> 5 #include <iostream> 6 #include <numeric> 7 #include <string> 8 #include <vector> 9 10 #include "GradeCalc.hpp" 11 12 GradeCalc::GradeCalc(const std::string &cname):course_name{cname},is_dirty{true} { 13 counts.fill(0); 14 rates.fill(0); 15 } 16 17 void GradeCalc::input(int n) { 18 if(n < 0) { 19 std::cerr << "无效输入! 人数不能为负数\n"; 20 std::exit(1); 21 } 22 23 grades.reserve(n); 24 25 int grade; 26 27 for(int i = 0; i < n;) { 28 std::cin >> grade; 29 30 if(grade < 0 || grade > 100) { 31 std::cerr << "无效输入! 分数须在[0,100]\n"; 32 continue; 33 } 34 35 grades.push_back(grade); 36 ++i; 37 } 38 39 is_dirty = true; // 设置脏标记:成绩信息有变更 40 } 41 42 void GradeCalc::output() const { 43 for(auto grade: grades) 44 std::cout << grade << ' '; 45 std::cout << std::endl; 46 } 47 48 void GradeCalc::sort(bool ascending) { 49 if(ascending) 50 std::sort(grades.begin(), grades.end()); 51 else 52 std::sort(grades.begin(), grades.end(), std::greater<int>()); 53 } 54 55 int GradeCalc::min() const { 56 if(grades.empty()) 57 return -1; 58 59 auto it = std::min_element(grades.begin(), grades.end()); 60 return *it; 61 } 62 63 int GradeCalc::max() const { 64 if(grades.empty()) 65 return -1; 66 67 auto it = std::max_element(grades.begin(), grades.end()); 68 return *it; 69 } 70 71 double GradeCalc::average() const { 72 if(grades.empty()) 73 return 0.0; 74 75 double avg = std::accumulate(grades.begin(), grades.end(), 0.0)/grades.size(); 76 return avg; 77 } 78 79 void GradeCalc::info() { 80 if(is_dirty) 81 compute(); 82 83 std::cout << "课程名称:\t" << course_name << std::endl; 84 std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl; 85 std::cout << "最高分:\t" << max() << std::endl; 86 std::cout << "最低分:\t" << min() << std::endl; 87 88 const std::array<std::string, 5> grade_range{"[0, 60) ", 89 "[60, 70)", 90 "[70, 80)", 91 "[80, 90)", 92 "[90, 100]"}; 93 94 for(int i = static_cast<int>(grade_range.size())-1; i >= 0; --i) 95 std::cout << grade_range[i] << "\t: " << counts[i] << "人\t" 96 << std::fixed << std::setprecision(2) << rates[i]*100 << "%\n"; 97 } 98 99 void GradeCalc::compute() { 100 if(grades.empty()) 101 return; 102 103 counts.fill(0); 104 rates.fill(0.0); 105 106 // 统计各分数段人数 107 for(auto grade:grades) { 108 if(grade < 60) 109 ++counts[0]; // [0, 60) 110 else if (grade < 70) 111 ++counts[1]; // [60, 70) 112 else if (grade < 80) 113 ++counts[2]; // [70, 80) 114 else if (grade < 90) 115 ++counts[3]; // [80, 90) 116 else 117 ++counts[4]; // [90, 100] 118 } 119 120 // 统计各分数段比例 121 for(size_t i = 0; i < rates.size(); ++i) 122 rates[i] = counts[i] * 1.0 / grades.size(); 123 124 is_dirty = false; // 更新脏标记 125 }
1 #pragma once 2 3 #include <vector> 4 #include <array> 5 #include <string> 6 7 class GradeCalc { 8 public: 9 GradeCalc(const std::string &cname); 10 void input(int n); // 录入n个成绩 11 void output() const; // 输出成绩 12 void sort(bool ascending = false); // 排序 (默认降序) 13 int min() const; // 返回最低分(如成绩未录入,返回-1) 14 int max() const; // 返回最高分 (如成绩未录入,返回-1) 15 double average() const; // 返回平均分 (如成绩未录入,返回0.0) 16 void info(); // 输出课程成绩信息 17 18 private: 19 void compute(); // 成绩统计 20 21 private: 22 std::string course_name; // 课程名 23 std::vector<int> grades; // 课程成绩 24 std::array<int, 5> counts; // 保存各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100] 25 std::array<double, 5> rates; // 保存各分数段人数占比 26 bool is_dirty; // 脏标记,记录是否成绩信息有变更 27 };
1 #include <iostream> 2 #include <string> 3 #include "GradeCalc.hpp" 4 5 void test() { 6 GradeCalc c1("OOP"); 7 8 std::cout << "录入成绩:\n"; 9 c1.input(5); 10 11 std::cout << "输出成绩:\n"; 12 c1.output(); 13 14 std::cout << "排序后成绩:\n"; 15 c1.sort(); c1.output(); 16 17 std::cout << "*************成绩统计信息*************\n"; 18 c1.info(); 19 20 } 21 22 int main() { 23 test(); 24 }
运行结果截图

问题1:GradeCalc 类声明中,逐行写出所有体现"组合"关系的成员声明,并用一句话说明每个被组合对象的功能。
std::string course_name:存储课程名称
std::vector<int> grades:存储学生课程成绩
std::array<int, 5> counts:存储各分数段学生人数
std::array<double, 5> rates:存储各分数段人数占比
问题2:如在 test 模块中这样使用,是否合法?如不合法,解释原因。
GradeCalc c("OOP");
c.input(5);
c.push_back(97); // 合法吗?
不合法。push_back()是vector的成员函数,而grades是GradeCalc的私有成员,类外部无法直接访问调用。
问题3:当前设计方案中, compute 在 info 模块中调用:
(1)连续打印3次统计信息, compute 会被调用几次?标记 is_dirty 起到什么作用?
1 次。is_dirty标记成绩数据是否变更,未变更则重复打印时不重复调用compute,提升效率。
(2)如新增 update_grade(index, new_grade) ,这种设计需要更改 compute 调用位置吗?简洁说明理由。
不需要。新增update_grade时只需修改is_dirty为true,info调用时会自动触发compute,无需改调用位置。
问题4:要增加"中位数"统计,不新增数据成员怎么做?在哪个函数里加?写出伪代码。
在GradeCalc中新增middle()方法,在info()中调用输出,不新增数据成员。
1 double GradeCalc::middle() { 2 if (grades.empty()) return 0; 3 std::vector<int> temp = grades; 4 std::sort(temp.begin(), temp.end()); 5 int n = temp.size(); 6 return n % 2 ? temp[n/2] : (temp[n/2-1] + temp[n/2])/2.0; 7 } 8 // info()中添加: 9 std::cout << "中位数:\t" << std::fixed << std::setprecision(2) << middle() << std::endl;
问题5:GradeCalc 和 compute 中都包含代码: counts.fill(0); rates.fill(0); compute 中能否去掉这两行?如去掉,在哪种使用场景下会引发统计错误?
不能去掉。若去掉,多次调用compute(如成绩更新后重复统计)时,counts和rates会在原有结果上累加,导致统计数据错误。
问题6:input 模块中代码 grades.reserve(n); 如果去掉:
(1)对程序功能有影响吗?(去掉重新编译、运行,观察功能是否受影响)
无影响,程序可正常编译运行。
(2)对性能有影响吗?如有影响,用一句话陈述具体影响。
有影响,vector 会频繁重新分配内存并拷贝数据,导致大数据量输入时性能下降。
二、实验任务2
源代码task2
1 #include <algorithm> 2 #include <array> 3 #include <cstdlib> 4 #include <iomanip> 5 #include <iostream> 6 #include <numeric> 7 #include <string> 8 #include <vector> 9 #include "GradeCalc.hpp" 10 11 12 GradeCalc::GradeCalc(const std::string &cname): course_name{cname}, is_dirty{true}{ 13 counts.fill(0); 14 rates.fill(0); 15 } 16 17 void GradeCalc::input(int n) { 18 if(n < 0) { 19 std::cerr << "无效输入! 人数不能为负数\n"; 20 return; 21 } 22 23 this->reserve(n); 24 25 int grade; 26 27 for(int i = 0; i < n;) { 28 std::cin >> grade; 29 if(grade < 0 || grade > 100) { 30 std::cerr << "无效输入! 分数须在[0,100]\n"; 31 continue; 32 } 33 34 this->push_back(grade); 35 ++i; 36 } 37 38 is_dirty = true; 39 } 40 41 void GradeCalc::output() const { 42 for(auto grade: *this) 43 std::cout << grade << ' '; 44 std::cout << std::endl; 45 } 46 47 void GradeCalc::sort(bool ascending) { 48 if(ascending) 49 std::sort(this->begin(), this->end()); 50 else 51 std::sort(this->begin(), this->end(), std::greater<int>()); 52 } 53 54 int GradeCalc::min() const { 55 if(this->empty()) 56 return -1; 57 58 return *std::min_element(this->begin(), this->end()); 59 } 60 61 int GradeCalc::max() const { 62 if(this->empty()) 63 return -1; 64 65 return *std::max_element(this->begin(), this->end()); 66 } 67 68 double GradeCalc::average() const { 69 if(this->empty()) 70 return 0.0; 71 72 double avg = std::accumulate(this->begin(), this->end(), 0.0) / this->size(); 73 return avg; 74 } 75 76 void GradeCalc::info() { 77 if(is_dirty) 78 compute(); 79 80 std::cout << "课程名称:\t" << course_name << std::endl; 81 std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl; 82 std::cout << "最高分:\t" << max() << std::endl; 83 std::cout << "最低分:\t" << min() << std::endl; 84 85 const std::array<std::string, 5> grade_range{"[0, 60) ", 86 "[60, 70)", 87 "[70, 80)", 88 "[80, 90)", 89 "[90, 100]"}; 90 91 for(int i = static_cast<int>(grade_range.size())-1; i >= 0; --i) 92 std::cout << grade_range[i] << "\t: " << counts[i] << "人\t" 93 << std::fixed << std::setprecision(2) << rates[i]*100 << "%\n"; 94 } 95 96 void GradeCalc::compute() { 97 if(this->empty()) 98 return; 99 100 counts.fill(0); 101 rates.fill(0); 102 103 // 统计各分数段人数 104 for(int grade: *this) { 105 if(grade < 60) 106 ++counts[0]; // [0, 60) 107 else if (grade < 70) 108 ++counts[1]; // [60, 70) 109 else if (grade < 80) 110 ++counts[2]; // [70, 80) 111 else if (grade < 90) 112 ++counts[3]; // [80, 90) 113 else 114 ++counts[4]; // [90, 100] 115 } 116 117 // 统计各分数段比例 118 for(size_t i = 0; i < rates.size(); ++i) 119 rates[i] = counts[i] * 1.0 / this->size(); 120 121 is_dirty = false; 122 }
1 #pragma once 2 3 #include <array> 4 #include <string> 5 #include <vector> 6 7 class GradeCalc: private std::vector<int> { 8 public: 9 GradeCalc(const std::string &cname); 10 void input(int n); // 录入n个成绩 11 void output() const; // 输出成绩 12 void sort(bool ascending = false); // 排序 (默认降序) 13 int min() const; // 返回最低分 14 int max() const; // 返回最高分 15 double average() const; // 返回平均分 16 void info(); // 输出成绩统计信息 17 18 private: 19 void compute(); // 计算成绩统计信息 20 21 private: 22 std::string course_name; // 课程名 23 std::array<int, 5> counts; // 保存各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100] 24 std::array<double, 5> rates; // 保存各分数段占比 25 bool is_dirty; // 脏标记,记录是否成绩信息有变更 26 };
1 #include <iostream> 2 #include <string> 3 #include "GradeCalc.hpp" 4 5 void test() { 6 GradeCalc c1("OOP"); 7 8 std::cout << "录入成绩:\n"; 9 c1.input(5); 10 11 std::cout << "输出成绩:\n"; 12 c1.output(); 13 14 std::cout << "排序后成绩:\n"; 15 c1.sort(); c1.output(); 16 17 std::cout << "*************成绩统计信息*************\n"; 18 c1.info(); 19 20 } 21 22 int main() { 23 test(); 24 }
运行结果截图

问题1:写出 GradeCalc 类声明体现"继承"关系的完整代码行。
class GradeCalc : private std::vector<int>
问题2:当前继承方式下,基类 vector<int> 的接口会自动成为 GradeCalc 的接口吗?如在 test 模块中这样用,能否编译通过?用一句话解释原因。
GradeCalc c("OOP");
c.input(5);
c.push_back(97); // 合法吗?
基类vector<int>的接口不会自动成为GradeCalc的接口,编译不能通过。原因:private 继承会将基类接口设为私有,类外部无法直接调用push_back等基类方法。
问题3: 对比继承方式与组合方式内部实现数据访问的一行典型代码。说明两种方式下的封装差异带来的数据访问接口差异。
// 组合方式
for(auto grade: grades) // 通过什么接口访问数据
// 略
// 继承方式
for(int grade: *this) // 通过什么接口访问数据
// 略
组合方式:for(auto grade: grades),通过类的私有成员变量grades(组合的容器对象)访问数据;
继承方式:for(int grade: *this),通过派生类自身(this指针指向的基类实例)的迭代器接口访问数据。
封装差异:组合方式封装性更强,数据通过成员变量间接访问,外部无法直接操作;继承方式封装性较弱,派生类可直接复用基类接口,易暴露不必要的操作。
问题4:你认为组合方案和继承方案,哪个更适合成绩计算这个问题场景?简洁陈述你的结论和理由。
组合方案更适合。理由:1.符合 “成绩统计类包含成绩容器” 的逻辑关系,而非 “成绩统计类是容器” 的继承关系;2.封装性更强,避免暴露vector的无关接口(如push_back),数据安全性更高;3.扩展性更好,后期更换存储容器时只需修改内部成员,不影响外部调用。
三、实验任务3
源代码task3
1 #include <algorithm> 2 #include <cctype> 3 #include <iostream> 4 #include <string> 5 6 #include "Graph.hpp" 7 8 // Circle类实现 9 void Circle::draw() { std::cout << "draw a circle...\n"; } 10 11 // Triangle类实现 12 void Triangle::draw() { std::cout << "draw a triangle...\n"; } 13 14 // Rectangle类实现 15 void Rectangle::draw() { std::cout << "draw a rectangle...\n"; } 16 17 // Canvas类实现 18 void Canvas::add(const std::string& type) { 19 Graph* g = make_graph(type); 20 if (g) 21 graphs.push_back(g); 22 } 23 24 void Canvas::paint() const { 25 for (Graph* g : graphs) 26 g->draw(); 27 } 28 29 Canvas::~Canvas() { 30 for (Graph* g : graphs) 31 delete g; 32 } 33 34 // 工具函数实现 35 // 字符串 → 枚举转换 36 GraphType str_to_GraphType(const std::string& s) { 37 std::string t = s; 38 std::transform(s.begin(), s.end(), t.begin(), 39 [](unsigned char c) { return std::tolower(c);}); 40 41 if (t == "circle") 42 return GraphType::circle; 43 44 if (t == "triangle") 45 return GraphType::triangle; 46 47 if (t == "rectangle") 48 return GraphType::rectangle; 49 50 return GraphType::circle; // 缺省返回 51 } 52 53 // 创建图形,返回堆对象指针 54 Graph* make_graph(const std::string& type) { 55 switch (str_to_GraphType(type)) { 56 case GraphType::circle: return new Circle; 57 case GraphType::triangle: return new Triangle; 58 case GraphType::rectangle: return new Rectangle; 59 default: return nullptr; 60 } 61 }
1 #pragma once 2 3 #include <string> 4 #include <vector> 5 6 enum class GraphType {circle, triangle, rectangle}; 7 8 // Graph类定义 9 class Graph { 10 public: 11 virtual void draw() {} 12 virtual ~Graph() = default; 13 }; 14 15 // Circle类声明 16 class Circle : public Graph { 17 public: 18 void draw(); 19 }; 20 21 // Triangle类声明 22 class Triangle : public Graph { 23 public: 24 void draw(); 25 }; 26 27 // Rectangle类声明 28 class Rectangle : public Graph { 29 public: 30 void draw(); 31 }; 32 33 // Canvas类声明 34 class Canvas { 35 public: 36 void add(const std::string& type); // 根据字符串添加图形 37 void paint() const; // 使用统一接口绘制所有图形 38 ~Canvas(); // 手动释放资源 39 40 private: 41 std::vector<Graph*> graphs; 42 }; 43 44 // 4. 工具函数 45 GraphType str_to_GraphType(const std::string& s); // 字符串转枚举类型 46 Graph* make_graph(const std::string& type); // 创建图形,返回堆对象指针
1 #include <string> 2 #include "Graph.hpp" 3 4 void test() { 5 Canvas canvas; 6 7 canvas.add("circle"); 8 canvas.add("triangle"); 9 canvas.add("rectangle"); 10 canvas.paint(); 11 } 12 13 int main() { 14 test(); 15 }
运行结果截图

问题1:
(1)写出Graph.hpp中体现"组合"关系的成员声明代码行,并用一句话说明被组合对象的功能。
Canvas类中:std::vector<Graph*> graphs;,功能是存储指向各类图形对象(Graph 派生类实例)的指针,实现图形集合管理。
(2)写出Graph.hpp中体现"继承"关系的类声明代码行。
class Circle : public Graph;
class Triangle : public Graph;
class Rectangle : public Graph;
问题2:
(1) Graph 中的 draw 若未声明成虚函数, Canvas::paint() 中 g->draw() 运行结果会有何不同?
所有g->draw()都会调用基类Graph的draw函数,无法触发派生类(圆形、三角形等)的重写实现,丧失多态特性。
(2)若 Canvas 类 std::vector<Graph*> 改成 std::vector<Graph> ,会出现什么问题?
会发生 “对象切片”,存储时仅拷贝派生类的基类部分,派生类特有成员和重写接口丢失,调用draw时始终执行基类逻辑,且无法体现多态。
(3)若 ~Graph() 未声明成虚函数,会带来什么问题?
析构基类指针指向的派生类对象时,仅调用基类析构函数,派生类中堆内存资源无法释放,导致内存泄漏。
问题3: 若要新增星形 Star ,需在哪些文件做哪些改动?逐一列出。
Graph.hpp:1.新增Star类继承Graph,声明draw纯虚函数实现;2.在GraphType枚举中添加star枚举值。
Graph.cpp:1.实现Star::draw()函数(输出绘图逻辑);2.在str_to_GraphType函数中添加分支:若输入字符串为 "star",返回GraphType::star;3.在make_graph函数中添加case GraphType::star,返回new Star()。
task3.cpp:在测试代码中添加canvas.add("star"),将星形图形加入画布。
问题4:观察 make_graph 函数和 Canvas 析构函数:
(1) make_graph 返回的对象在什么地方被释放?
make_graph返回的堆上图形对象,在Canvas类的析构函数中被释放(通过遍历graphs容器,对每个指针调用delete)。
(2)使用原始指针管理内存有何利弊?
利:使用简单、直观,无需依赖额外工具(如智能指针),学习成本低;
弊:需手动管理内存释放,易因遗漏delete、重复释放或野指针导致内存泄漏,安全性较低。
四、实验任务4
1 #ifndef TOY_SYSTEM_HPP 2 #define TOY_SYSTEM_HPP 3 4 #include <string> 5 #include <vector> 6 #include <iostream> 7 #include <iomanip> 8 9 class Toy { 10 protected: 11 std::string name; 12 std::string type; 13 double price; 14 std::string manufacturer; 15 int batteryLevel; 16 17 public: 18 Toy(std::string name, std::string type, double price, 19 std::string manufacturer, int batteryLevel); 20 21 void showBasicInfo() const; 22 virtual void showSpecialFunction() const = 0; 23 virtual ~Toy() {} 24 }; 25 26 class GlowingToy : public Toy { 27 private: 28 std::string lightColor; 29 std::string lightMode; 30 31 public: 32 GlowingToy(std::string name, double price, std::string manufacturer, 33 int batteryLevel, std::string lightColor, std::string lightMode); 34 void showSpecialFunction() const override; 35 }; 36 37 class TalkingToy : public Toy { 38 private: 39 std::string language; 40 int phraseCount; 41 42 public: 43 TalkingToy(std::string name, double price, std::string manufacturer, 44 int batteryLevel, std::string language, int phraseCount); 45 void showSpecialFunction() const override; 46 }; 47 48 class DancingToy : public Toy { 49 private: 50 int danceMoves; 51 bool hasMusic; 52 53 public: 54 DancingToy(std::string name, double price, std::string manufacturer, 55 int batteryLevel, int danceMoves, bool hasMusic); 56 void showSpecialFunction() const override; 57 }; 58 59 class ToyFactory { 60 private: 61 std::string factoryName; 62 std::vector<Toy*> toyList; 63 64 public: 65 ToyFactory(std::string name); 66 void addToy(Toy* toy); 67 void displayAllToys() const; 68 ~ToyFactory(); 69 }; 70 71 #endif
1 #include "toy_system.hpp" 2 3 Toy::Toy(std::string name, std::string type, double price, 4 std::string manufacturer, int batteryLevel) 5 : name(name), type(type), price(price), 6 manufacturer(manufacturer), batteryLevel(batteryLevel) {} 7 8 void Toy::showBasicInfo() const { 9 std::cout << "【基本信息】" << std::endl; 10 std::cout << "玩具名称: " << name << std::endl; 11 std::cout << "玩具类型: " << type << std::endl; 12 std::cout << "价格: ¥" << std::fixed << std::setprecision(2) << price << std::endl; 13 std::cout << "生产厂家: " << manufacturer << std::endl; 14 std::cout << "当前电量: " << batteryLevel << "%" << std::endl; 15 } 16 17 GlowingToy::GlowingToy(std::string name, double price, std::string manufacturer, 18 int batteryLevel, std::string lightColor, std::string lightMode) 19 : Toy(name, "发光毛绒玩具", price, manufacturer, batteryLevel), 20 lightColor(lightColor), lightMode(lightMode) {} 21 22 void GlowingToy::showSpecialFunction() const { 23 std::cout << "【特异功能】" << std::endl; 24 std::cout << "功能类型: 七彩发光" << std::endl; 25 std::cout << "发光颜色: " << lightColor << std::endl; 26 std::cout << "发光模式: " << lightMode << std::endl; 27 } 28 29 TalkingToy::TalkingToy(std::string name, double price, std::string manufacturer, 30 int batteryLevel, std::string language, int phraseCount) 31 : Toy(name, "语音对话玩具", price, manufacturer, batteryLevel), 32 language(language), phraseCount(phraseCount) {} 33 34 void TalkingToy::showSpecialFunction() const { 35 std::cout << "【特异功能】" << std::endl; 36 std::cout << "功能类型: 智能对话" << std::endl; 37 std::cout << "支持语言: " << language << std::endl; 38 std::cout << "内置短语: " << phraseCount << "句" << std::endl; 39 } 40 41 DancingToy::DancingToy(std::string name, double price, std::string manufacturer, 42 int batteryLevel, int danceMoves, bool hasMusic) 43 : Toy(name, "舞蹈玩具", price, manufacturer, batteryLevel), 44 danceMoves(danceMoves), hasMusic(hasMusic) {} 45 46 void DancingToy::showSpecialFunction() const { 47 std::cout << "【特异功能】" << std::endl; 48 std::cout << "功能类型: 欢乐舞蹈" << std::endl; 49 std::cout << "舞蹈动作: " << danceMoves << "种" << std::endl; 50 std::cout << "音乐播放: " << (hasMusic ? "支持" : "不支持") << std::endl; 51 } 52 53 ToyFactory::ToyFactory(std::string name) : factoryName(name) {} 54 55 void ToyFactory::addToy(Toy* toy) { 56 if (toy != nullptr) { 57 toyList.push_back(toy); 58 } 59 } 60 61 void ToyFactory::displayAllToys() const { 62 std::cout << "========== " << factoryName << " 玩具展示 ==========" << std::endl; 63 64 for (size_t i = 0; i < toyList.size(); ++i) { 65 std::cout << "\n第 " << (i + 1) << " 款玩具:" << std::endl; 66 toyList[i]->showBasicInfo(); 67 toyList[i]->showSpecialFunction(); 68 std::cout << "-----------------------------------" << std::endl; 69 } 70 } 71 72 ToyFactory::~ToyFactory() { 73 for (Toy* toy : toyList) { 74 delete toy; 75 } 76 toyList.clear(); 77 }
1 #include "toy_system.hpp" 2 3 int main() { 4 ToyFactory factory("智能玩具厂"); 5 6 Toy* bear = new GlowingToy("闪光熊", 88.0, "小熊公司", 80, "七彩", "呼吸灯"); 7 Toy* rabbit = new TalkingToy("对话兔", 120.0, "乐乐厂", 65, "中英文", 200); 8 Toy* panda = new DancingToy("舞蹈熊猫", 150.0, "国宝玩具", 90, 5, true); 9 10 factory.addToy(bear); 11 factory.addToy(rabbit); 12 factory.addToy(panda); 13 14 factory.displayAllToys(); 15 16 return 0; 17 }
运行测试截图

设计总结:
系统通过继承实现多态,统一管理不同功能类型的玩具。ToyFactory类组合管理玩具集合,提供批量展示功能。虚函数机制确保统一接口调用不同特异功能,具有良好的扩展性。
实验总结:
通过本次实验,我深入理解了组合与继承在面向对象设计中的应用。继承实现了多态特性,允许通过统一接口调用不同功能;组合则建立了对象间的层次关系,提升了系统的灵活性。
虚函数的运用是本次实验的关键,它实现了"一个接口,多种实现"的设计理念,为系统扩展提供了良好基础。这次实践让我掌握了在不同场景下选择合适设计模式的方法。
浙公网安备 33010602011771号