实验4

一.任务1

1.源代码

  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 }
GradeCalc.cpp
 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 };
GradeCalc.hpp
 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 }
task1.cpp

2.运行结果截图

task1

3.问题1

所有体现"组合"关系的成员声明:
std::string course_name; // 用于存储课程名称
std::vector<int> grades; // 用于存储所有学生的成绩
std::array<int, 5> counts; // 用于统计五个分数段的学生人数
std::array<double, 5> rates; // 用于存储各分数段的百分比

4.问题2

不合法。
原因是:push_back(97) 是 std::vector<int> 的成员函数,在组合方案中,grades 是 GradeCalc 类的私有成员,外部代码无法直接访问 grades ,因此不能调用push_back,只能通过 GradeCalc 类提供的公共接口来添加成绩。

5.问题3

(1)连续打印3次统计信息,compute 会被调用 1次。
标记is_dirty 的作用:使得只有当成绩数据发生变化时,is_dirty = true才重新计算统计信息。这样可以避免重复计算,提高程序运行的性能。
(2)不需要更改 compute 调用位置。
理由是:compute是否被调用与is_dirty的值有关的,而非和调用位置有关

6.问题4

在 info() 函数中添加“中位数”统计,伪代码如下
double median() const {
if (grades.empty()) return 0.0;
// 创建成绩副本并排序
std::vector<int> sorted_grades = grades;
std::sort(sorted_grades.begin(), sorted_grades.end());
size_t size = sorted_grades.size();
// 偶数个:取中间两个数的平均值
if (size % 2 == 0) {
return (sorted_grades[size/2 - 1] + sorted_grades[size/2]) / 2.0;
} else {
// 奇数个:取中间数
return sorted_grades[size/2];
}
}

7.问题5

不能去掉。如果去掉这两行,则在成绩更新的场景下:如果先录入成绩A,计算统计信息,然后修改部分成绩为B,再次计算时,统计结果会是A+B的叠加,而不是B的正确统计。

8.问题6

(1)对程序功能 没有影响
(2)对性能 有影响,当录入大量成绩时,vector会频繁进行内存重新分配和数据拷贝,导致性能下降,而reserve(n)可以预先分配足够内存,避免了插入过程中的多次内存重分配的情况。

二.任务2

1.源代码

  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 }
GradeCalc.cpp
 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 };
GradeCalc.hpp
 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 }
task2.cpp

2.运行结果截图

屏幕截图 2025-11-20 213617

3.问题1

体现"继承"关系的完整代码行是:
class GradeCalc: private std::vector<int>

4.问题2

不会自动成为。
不能编译通过。
原因:在私有继承方式下,基类std::vector<int>的所有公有和保护成员在派生类GradeCalc中都变成了私有成员,外部代码无法直接访问基类的接口。

5.问题3

差异在于:
①组合方式是把数据完全封装在GradeCalc内部,导致外部无法直接访问grades,只能通过GradeCalc提供的公共接口操作数据。
②继承方式则是让GradeCalc本身就是vector,所以内部可以直接使用基类的所有接口,但外部仍然受到访问控制限制。

6.问题4

我认为组合方案更适合成绩计算这个场景。
我的理由是:
①组合方案的设计思路更符合现实情况,成绩计算器是"使用"成绩数据来做计算,而不是"变成"成绩数据本身,所以组合方案可以满足这一点,而继承方案恰恰相反。
②在组合方式的下,我可以决定哪些功能对外暴露,哪些不可以,比如只让用户通过input()输入成绩,不能直接修改。这样可以提高程序的安全性,防止别人乱改成绩数据。
③在以后不用vector,改用其他方式存成绩时,组合方式改起来更容易,灵活性更强。

三.任务3

1.源代码

 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 }
Graph.cpp
 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);  // 创建图形,返回堆对象指针
Graph.hpp
 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 }
demo3.cpp

2.运行结果截图

屏幕截图 2025-11-26 090151

3.问题1

(1)组合关系:std::vector<Graph*> graphs; //用于存储和管理所有图形对象的指针
(2)继承关系:
class Circle : public Graph
class Triangle : public Graph
class Rectangle : public Graph

4.问题2

(1)如果Graph中的draw未声明成虚函数,那么Canvas::paint()中g->draw()将始终调用Graph基类的draw函数,运行结果会全部输出空的draw信息,不会调用子类的具体信息进行绘制。
(2) 若Canvas类std::vector<Graph*>改成std::vector<Graph>,那么派生类对象赋值给基类对象时,派生类特有部分会被切掉,无法存储派生类对象,只能存储Graph的基类对象,所以这样修改会导致其完全失去多态功能。
(3)若~Graph()未声明成虚函数,那么通过基类指针删除派生类对象时,只会调用基类的析构函数,派生类的析构函数不会被调用,所以派生类中分配的资源无法正确释放,导致内存泄漏。

5.问题3

若要新增星形Star,则
在Graph.hpp添加:
①在enum class GraphType中添加star枚举值
② 新增Star类声明,继承自Graph
在Graph.cpp中添加:
① 实现Star类的draw函数
②在str_to_GraphType函数中添加对"star"字符串的处理
③ 在make_graph函数中添加case GraphType::star的处理
6.问题4

(1)make_graph返回的对象在Canvas析构函数中被释放:
(2)使用原始指针管理内存的利弊:
利:
①使用原始指针更简单直接
②使用原始指针可以明确管理内存生命周期,所以可以对指针的控制更为精确。
弊:
①使用原始指针时,容易忘记释放内存,导致内存泄漏
②可能出现重复释放同一块内存

 四.任务4

1.问题场景描述
设计一个电子玩具管理系统,包含多种具有不同特异功能的玩具。通过工厂模式创建玩具,并能够统一展示所有玩具的特异功能。
2.各类之间的关系及设计理由
这个玩具系统采用的关系有:
①Toy基类与具体玩具类之间是继承关系,这样可以实现多态和代码复用;
②ToyFactory与Toy之间是组合关系,从而使工厂可以包含并管理多个玩具对象。
这样设计既符合现实逻辑,即工厂拥有玩具,又保证了系统的可扩展性和易维护性,能够方便地添加新玩具类型而不影响现有代码结构。

3.源代码

 1 #include "Toy.hpp"
 2 #include <vector>
 3 #include <iomanip>
 4 
 5 Toy::Toy(const std::string& name, const std::string& type, double price, 
 6          const std::string& material, const std::string& brand, const std::string& ageRange)
 7     : name_(name), type_(type), price_(price), material_(material), brand_(brand), ageRange_(ageRange) {}
 8 
 9 void Toy::displayInfo() const {
10     std::cout << "名称: " << name_ 
11               << "\t类型: " << type_ 
12               << "\t价格: ¥" << std::fixed << std::setprecision(2) << price_
13               << "\n材质: " << material_
14               << "\t品牌: " << brand_
15               << "\t适用年龄: " << ageRange_ << std::endl;
16 }
17 
18 // AIDog实现
19 AIDog::AIDog(const std::string& name, double price, const std::string& material, 
20              const std::string& brand, const std::string& ageRange)
21     : Toy(name, "人工智能狗", price, material, brand, ageRange) {}
22 
23 void AIDog::specialAbility() const {
24     std::cout << name_ << "启动AI对话: '你好主人!今天天气真不错,想和我聊点什么吗?'" << std::endl;
25 }
26 
27 // DancingDonkey实现
28 DancingDonkey::DancingDonkey(const std::string& name, double price, const std::string& material, 
29                              const std::string& brand, const std::string& ageRange)
30     : Toy(name, "跳舞的驴", price, material, brand, ageRange) {}
31 
32 void DancingDonkey::specialAbility() const {
33     std::cout << name_ << "开始跳舞:摇摆摇摆,跳起欢快的舞蹈!" << std::endl;
34 }
35 
36 // SelfPlayingGuitar实现
37 SelfPlayingGuitar::SelfPlayingGuitar(const std::string& name, double price, const std::string& material, 
38                                      const std::string& brand, const std::string& ageRange)
39     : Toy(name, "自动弹奏吉他", price, material, brand, ageRange) {}
40 
41 void SelfPlayingGuitar::specialAbility() const {
42     std::cout <<  name_ << "自动弹奏:请选择想要弹奏的音乐" << std::endl;
43 }
44 
45 // ToyFactory实现
46 ToyFactory::ToyFactory() {}
47 
48 ToyFactory::~ToyFactory() {
49     for (Toy* toy : toys_) {
50         delete toy;
51     }
52 }
53 
54 void ToyFactory::addToy(Toy* toy) {
55     if (toy) {
56         toys_.push_back(toy);
57     }
58 }
59 
60 void ToyFactory::displayAllToys() const {
61     std::cout << "\n======= 玩具工厂所有玩具 =======" << std::endl;
62     for (const Toy* toy : toys_) {
63         toy->displayInfo();
64     }
65 }
66 
67 void ToyFactory::tryAllAbilities() const {
68     std::cout << "\n======= 展示所有玩具特异功能 =======" << std::endl;
69     for (const Toy* toy : toys_) {
70         toy->specialAbility();
71     }
72 }
Toy.cpp
 1 #pragma once
 2 #include <string>
 3 #include <iostream>
 4 #include <vector> 
 5 // 玩具基类
 6 class Toy {
 7 public:
 8     Toy(const std::string& name, const std::string& type, double price, 
 9         const std::string& material, const std::string& brand, const std::string& ageRange);
10     virtual ~Toy() = default;
11     
12     virtual void specialAbility() const = 0;
13     virtual void displayInfo() const;
14 
15     std::string getName() const { return name_; }
16     std::string getType() const { return type_; }
17     double getPrice() const { return price_; }
18     std::string getMaterial() const { return material_; }
19     std::string getBrand() const { return brand_; }
20     std::string getAgeRange() const { return ageRange_; }
21 
22 protected:
23     std::string name_;      // 玩具名称
24     std::string type_;      // 玩具类型
25     double price_;          // 价格
26     std::string material_;  // 材质
27     std::string brand_;     // 品牌
28     std::string ageRange_;  // 适用年龄段
29 };
30 
31 // 人工智能狗
32 class AIDog : public Toy {
33 public:
34     AIDog(const std::string& name, double price, const std::string& material, 
35           const std::string& brand, const std::string& ageRange);
36     void specialAbility() const override;
37 };
38 
39 // 跳舞的驴
40 class DancingDonkey : public Toy {
41 public:
42     DancingDonkey(const std::string& name, double price, const std::string& material, 
43                   const std::string& brand, const std::string& ageRange);
44     void specialAbility() const override;
45 };
46 
47 // 自动弹奏吉他
48 class SelfPlayingGuitar : public Toy {
49 public:
50     SelfPlayingGuitar(const std::string& name, double price, const std::string& material, 
51                       const std::string& brand, const std::string& ageRange);
52     void specialAbility() const override;
53 };
54 
55 class ToyFactory {
56 public:
57     ToyFactory();
58     ~ToyFactory();  
59     
60     void addToy(Toy* toy);
61     void displayAllToys() const;  
62     void tryAllAbilities() const;
63 
64 private:
65     std::vector<Toy*> toys_;  
66 };
Toy.hpp
 1 #include <iostream>
 2 #include "Toy.hpp"
 3 
 4 void testToySystem() {
 5     // 创建玩具工厂
 6     ToyFactory factory;
 7     factory.addToy(new AIDog("小智", 299.99, "硅胶", "AI宠物", "3-8岁"));
 8     factory.addToy(new DancingDonkey("欢欢", 159.50, "毛绒", "欢乐玩具", "2-6岁"));
 9     factory.addToy(new SelfPlayingGuitar("音乐家", 399.00, "木材+电子元件", "音乐大师", "5-12岁"));
10     factory.addToy(new AIDog("旺财", 349.99, "高级硅胶", "智能伙伴", "4-10岁"));
11     factory.addToy(new DancingDonkey("跳跳", 179.00, "优质毛绒", "舞蹈世家", "3-7岁"));
12     // 显示所有玩具信息
13     factory.displayAllToys();
14     // 展示所有玩具的特异功能
15     factory.tryAllAbilities();
16 }
17 
18 int main() {
19     testToySystem();
20     return 0;
21 }
demo4.cpp

4.运行结果截图

屏幕截图 2025-11-26 230117

五.实验总结

1.本次实验让我深入理解了组合与继承的核心差异。通过成绩计算器和图形系统的实现,我体会到组合更注重"拥有"关系,所以其封装性较好;而继承则体现的是"是"关系,从而便于多态扩展。

2.疑问:

在学习过程中,我最大的困惑在于:首先,在设计复杂系统时,如何准确判断该用组合还是继承?其次,虚函数的底层机制较抽象,导致在进行多态应用时对时机把握不到位。

 

posted @ 2025-11-26 23:59  flower00  阅读(2)  评论(0)    收藏  举报