实验四

任务一

代码

 1 #pragma once
 2 #include <vector>
 3 #include <array>
 4 #include <string>
 5 
 6 class GradeCalc {
 7 public:
 8     GradeCalc(const std::string &cname);      
 9     void input(int n);                         
10     void output() const;                      
11     void sort(bool ascending = false);        
12     int min() const;                          
13     int max() const;                          
14     double average() const;                   
15     void info();                              
16 
17 private:
18     void compute();                            
19 
20 private:
21     std::string course_name;  
22     std::vector<int> grades;  
23     std::array<int, 5> counts;                  
24     std::array<double, 5> rates;                
25     bool is_dirty;            
26 };
GradeCalc.hpp
  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 GradeCalc::GradeCalc(const std::string &cname) 
 12     : course_name{cname}, is_dirty{true} {
 13     counts.fill(0);
 14     rates.fill(0.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     int grade;
 25 
 26     for (int i = 0; i < n;) {
 27         std::cin >> grade;
 28         if (grade < 0 || grade > 100) {
 29             std::cerr << "无效输入! 分数须在[0,100]\n";
 30             continue;
 31         }
 32         grades.push_back(grade);
 33         ++i;
 34     }
 35 
 36     is_dirty = true;
 37 }
 38 
 39 void GradeCalc::output() const {
 40     for (auto grade : grades)
 41         std::cout << grade << ' ';
 42     std::cout << std::endl;
 43 }
 44 
 45 void GradeCalc::sort(bool ascending) {
 46     if (ascending)
 47         std::sort(grades.begin(), grades.end());
 48     else
 49         std::sort(grades.begin(), grades.end(), std::greater<int>());
 50 }
 51 
 52 int GradeCalc::min() const {
 53     if (grades.empty())
 54         return -1;
 55     auto it = std::min_element(grades.begin(), grades.end());
 56     return *it;
 57 }
 58 
 59 int GradeCalc::max() const {
 60     if (grades.empty())
 61         return -1;
 62     auto it = std::max_element(grades.begin(), grades.end());
 63     return *it;
 64 }
 65 
 66 double GradeCalc::average() const {
 67     if (grades.empty())
 68         return 0.0;
 69     double avg = std::accumulate(grades.begin(), grades.end(), 0.0) / grades.size();
 70     return avg;
 71 }
 72 
 73 void GradeCalc::info() {
 74     if (is_dirty)
 75         compute();
 76 
 77     std::cout << "课程名称:\t" << course_name << std::endl;
 78     std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl;
 79     std::cout << "最高分:\t" << max() << std::endl;
 80     std::cout << "最低分:\t" << min() << std::endl;
 81 
 82     const std::array<std::string, 5> grade_range{
 83         "[0, 60) ", "[60, 70)", "[70, 80)", "[80, 90)", "[90, 100]"
 84     };
 85 
 86     for (int i = static_cast<int>(grade_range.size()) - 1; i >= 0; --i) {
 87         std::cout << grade_range[i] << "\t: " << counts[i] << "人\t"
 88                   << std::fixed << std::setprecision(2) << rates[i] * 100 << "%\n";
 89     }
 90 }
 91 
 92 void GradeCalc::compute() {
 93     if (grades.empty())
 94         return;
 95 
 96     counts.fill(0);
 97     rates.fill(0.0);
 98 
 99     for (auto grade : grades) {
100         if (grade < 60)
101             ++counts[0];
102         else if (grade < 70)
103             ++counts[1];
104         else if (grade < 80)
105             ++counts[2];
106         else if (grade < 90)
107             ++counts[3];
108         else
109             ++counts[4];
110     }
111 
112     for (size_t i = 0; i < rates.size(); ++i) {
113         rates[i] = counts[i] * 1.0 / grades.size();
114     }
115 
116     is_dirty = false;
117 }
GradeCalc.cpp
 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();
16     c1.output();
17 
18     std::cout << "*************成绩统计信息*************\n";
19     c1.info();
20 }
21 
22 int main() {
23     test();
24     return 0;
25 }
task1.cpp

效果

283037ff8767db3f1914028719de6468

 问题

问题1:
std::string course_name; // 记录课程名称
std::vector<int> grades; // 保存所有学生的成绩
std::array<int, 5> counts; // 统计五个分数段的学生人数
std::array<double, 5> rates; // 保存各分数段人数占总人数的比例

问题2:
不合法。原因是`push_back`是`std::vector<int>`的成员函数,而`grades`是`GradeCalc`类的私有成员,外部代码无法直接访问私有成员,且`GradeCalc`类未提供对应的公有接口,因此不能直接调用`push_back`添加成绩。

问题3:
(1)compute会被调用1次。`is_dirty`是脏标记,用于判断成绩数据是否发生变更,只有当数据变更(`is_dirty = true`)时,调用`info`才会重新执行`compute`计算统计信息,避免重复计算以提升性能。
(2)不需要更改`compute`调用位置。理由是`compute`的调用由`is_dirty`的状态决定,新增`update_grade(index, new_grade)`时,只需在该方法中设置`is_dirty = true`,后续调用`info`时会自动检测状态并触发`compute`,无需调整调用位置。

问题4

不新增数据成员的实现方式:新增`median`成员函数,利用已有的`grades`数据,通过复制成绩并排序的方式计算中位数,在`info`函数中调用该函数并输出结果。代码如下:
double GradeCalc::median() const {
if (grades.empty())
return 0.0;
std::vector<int> sorted_grades = grades; // 复制成绩,避免修改原数据
std::sort(sorted_grades.begin(), sorted_grades.end());
size_t n = sorted_grades.size();
if (n % 2 == 1) {
return sorted_grades[n / 2]; // 奇数个数据取中间值
} else {
return (sorted_grades[n / 2 - 1] + sorted_grades[n / 2]) / 2.0; // 偶数个数据取中间两值平均
}
}
```
在`info`函数中添加输出逻辑:`std::cout << "中位数:\t" << std::fixed << std::setprecision(2) << median() << std::endl;`

问题5
不能去掉这两行。如果去掉,当存在成绩更新场景(如先录入成绩计算统计信息,后修改部分成绩再重新计算)时,`counts`和`rates`会在原有统计结果的基础上叠加新数据,导致统计结果错误,无法反映修改后成绩的真实分布。

问题6
(1)对程序功能没有影响,去掉后程序仍能正常编译运行,成绩录入和统计功能不受影响。
(2)对性能有影响。去掉`grades.reserve(n)`后,当录入大量成绩时,`vector`会因元素数量超过当前容量频繁触发扩容,每次扩容需重新分配内存并拷贝原有数据,导致程序运行效率下降。

任务二

代码

 1 #pragma once
 2 #include <array>
 3 #include <string>
 4 #include <vector>
 5 
 6 class GradeCalc : private std::vector<int> {
 7 public:
 8     GradeCalc(const std::string& cname);
 9     void input(int n);
10     void output() const;
11     void sort(bool ascending = false);
12     int min() const;
13     int max() const;
14     double average() const;
15     void info();
16 
17 private:
18     void compute();
19 
20 private:
21     std::string course_name;
22     std::array<int, 5> counts;
23     std::array<double, 5> rates;
24     bool is_dirty;
25 };
GradeCalc.hpp
  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 GradeCalc::GradeCalc(const std::string& cname) : course_name{ cname }, is_dirty{ true } {
 12     counts.fill(0);
 13     rates.fill(0);
 14 }
 15 
 16 void GradeCalc::input(int n) {
 17     if (n < 0) {
 18         std::cerr << "无效输入! 人数不能为负数\n";
 19         return;
 20     }
 21     this->reserve(n);
 22     int grade;
 23     for (int i = 0; i < n;) {
 24         std::cin >> grade;
 25         if (grade < 0 || grade > 100) {
 26             std::cerr << "无效输入! 分数须在[0,100]\n";
 27             continue;
 28         }
 29         this->push_back(grade);
 30         ++i;
 31     }
 32     is_dirty = true;
 33 }
 34 
 35 void GradeCalc::output() const {
 36     for (auto grade : *this)
 37         std::cout << grade << ' ';
 38     std::cout << std::endl;
 39 }
 40 
 41 void GradeCalc::sort(bool ascending) {
 42     if (ascending)
 43         std::sort(this->begin(), this->end());
 44     else
 45         std::sort(this->begin(), this->end(), std::greater<int>());
 46 }
 47 
 48 int GradeCalc::min() const {
 49     if (this->empty())
 50         return -1;
 51     return *std::min_element(this->begin(), this->end());
 52 }
 53 
 54 int GradeCalc::max() const {
 55     if (this->empty())
 56         return -1;
 57     return *std::max_element(this->begin(), this->end());
 58 }
 59 
 60 double GradeCalc::average() const {
 61     if (this->empty())
 62         return 0.0;
 63     double avg = std::accumulate(this->begin(), this->end(), 0.0) / this->size();
 64     return avg;
 65 }
 66 
 67 void GradeCalc::info() {
 68     if (is_dirty)
 69         compute();
 70     std::cout << "课程名称:\t" << course_name << std::endl;
 71     std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl;
 72     std::cout << "最高分:\t" << max() << std::endl;
 73     std::cout << "最低分:\t" << min() << std::endl;
 74     const std::array<std::string, 5> grade_range{ "[0, 60) ",
 75                                            "[60, 70)",
 76                                            "[70, 80)",
 77                                            "[80, 90)",
 78                                            "[90, 100]" };
 79     for (int i = static_cast<int>(grade_range.size()) - 1; i >= 0; --i)
 80         std::cout << grade_range[i] << "\t: " << counts[i] << "人\t"
 81         << std::fixed << std::setprecision(2) << rates[i] * 100 << "%\n";
 82 }
 83 
 84 void GradeCalc::compute() {
 85     if (this->empty())
 86         return;
 87     counts.fill(0);
 88     rates.fill(0);
 89     for (int grade : *this) {
 90         if (grade < 60)
 91             ++counts[0];
 92         else if (grade < 70)
 93             ++counts[1];
 94         else if (grade < 80)
 95             ++counts[2];
 96         else if (grade < 90)
 97             ++counts[3];
 98         else
 99             ++counts[4];
100     }
101     for (size_t i = 0; i < rates.size(); ++i)
102         rates[i] = counts[i] * 1.0 / this->size();
103     is_dirty = false;
104 }
GradeCalc.cpp
 1 #include <iostream>
 2 #include <string>
 3 #include "GradeCalc.hpp"
 4 
 5 void test() {
 6     GradeCalc c1("OOP");
 7     std::cout << "录入成绩:\n";
 8     c1.input(5);
 9     std::cout << "输出成绩:\n";
10     c1.output();
11     std::cout << "排序后成绩:\n";
12     c1.sort();
13     c1.output();
14     std::cout << "*************成绩统计信息*************\n";
15     c1.info();
16 }
17 
18 int main() {
19     test();
20 }
task2.cpp

效果

a4a5a9e7bfa45bc2ecc0c42c77c59855

 

 问题1
体现“继承”关系的完整代码行是:
`class GradeCalc: private std::vector<int>`


问题2
基类`std::vector<int>`的接口不会自动成为`GradeCalc`的接口。
`c.push_back(97);`不能编译通过,原因是:私有继承方式下,基类`std::vector<int>`的所有公有和保护成员在派生类`GradeCalc`中会成为私有成员,外部代码无法直接访问基类的接口。


 问题3
组合方式的典型代码:`for(auto grade: grades)`,通过类内部的成员对象接口访问数据;
继承方式的典型代码:`for(int grade: *this)`,通过派生类自身(复用基类)的接口访问数据。

两者的接口差异:
1. 组合方式中,数据被封装在类内部,外部无法直接访问数据成员,只能通过类提供的公共接口操作数据;
2. 继承方式中,派生类内部可直接使用基类的接口,但外部仍受访问控制限制,无法直接调用基类接口。


问题4
结论:组合方案更适合成绩计算的场景。
理由:
1. 组合的设计更符合实际逻辑:成绩计算器是“使用”成绩数据进行计算,而非“成为”成绩数据本身;
2. 组合可自主控制接口暴露,比如仅开放`input()`录入成绩,避免外部直接修改数据,提升了程序安全性;
3. 组合的灵活性更强,若后续更换成绩的存储方式(不用`vector`),仅需修改类内的成员对象,无需调整类的继承关系。

任务三

 1 #pragma once
 2 #include <string>
 3 #include <vector>
 4 
 5 enum class GraphType { circle, triangle, rectangle };
 6 
 7 class Graph {
 8 public:
 9     virtual void draw() {}
10     virtual ~Graph() = default;
11 };
12 
13 class Circle : public Graph {
14 public:
15     void draw() override;
16 };
17 
18 class Triangle : public Graph {
19 public:
20     void draw() override;
21 };
22 
23 class Rectangle : public Graph {
24 public:
25     void draw() override;
26 };
27 
28 class Canvas {
29 public:
30     void add(const std::string& type);
31     void paint() const;
32     ~Canvas();
33 
34 private:
35     std::vector<Graph*> graphs;
36 };
37 
38 GraphType str_to_GraphType(const std::string& s);
39 Graph* make_graph(const std::string& type);
Graph.hpp
 1 #include <algorithm>
 2 #include <cctype>
 3 #include <iostream>
 4 #include <string>
 5 #include "Graph.hpp"
 6 
 7 void Circle::draw() { std::cout << "draw a circle...\n"; }
 8 
 9 void Triangle::draw() { std::cout << "draw a triangle...\n"; }
10 
11 void Rectangle::draw() { std::cout << "draw a rectangle...\n"; }
12 
13 void Canvas::add(const std::string& type) {
14     Graph* g = make_graph(type);
15     if (g)
16         graphs.push_back(g);
17 }
18 
19 void Canvas::paint() const {
20     for (Graph* g : graphs)
21         g->draw();
22 }
23 
24 Canvas::~Canvas() {
25     for (Graph* g : graphs)
26         delete g;
27 }
28 
29 GraphType str_to_GraphType(const std::string& s) {
30     std::string t = s;
31     std::transform(s.begin(), s.end(), t.begin(),
32                    [](unsigned char c) { return std::tolower(c); });
33     if (t == "circle")
34         return GraphType::circle;
35     if (t == "triangle")
36         return GraphType::triangle;
37     if (t == "rectangle")
38         return GraphType::rectangle;
39     return GraphType::circle;
40 }
41 
42 Graph* make_graph(const std::string& type) {
43     switch (str_to_GraphType(type)) {
44     case GraphType::circle: return new Circle;
45     case GraphType::triangle: return new Triangle;
46     case GraphType::rectangle: return new Rectangle;
47     default: return nullptr;
48     }
49 }
Graph.cpp
 1 #include <iostream>
 2 #include <string>
 3 #include "Graph.hpp"
 4 
 5 void test() {
 6     Canvas canvas;
 7     canvas.add("circle");
 8     canvas.add("triangle");
 9     canvas.add("rectangle");
10     canvas.paint();
11 }
12 
13 int main() {
14     test();
15     return 0;
16 }
task3.cpp

效果

0458ab73c45cd86331b11114c733f38f

 

问题1:对象关系识别
(1)体现“组合”关系的成员声明代码行:`std::vector<Graph*> graphs;`
被组合对象的功能:用于存储和管理所有图形对象的指针。

(2)体现“继承”关系的类声明代码行:
`class Circle : public Graph`
`class Triangle : public Graph`
`class Rectangle : public Graph`


问题2:多态机制观察
(1)若Graph中的draw未声明为虚函数,Canvas::paint()中`g->draw()`会始终调用Graph基类的draw函数,运行时不会输出子类的绘制信息,仅执行基类的空draw逻辑。

(2)若Canvas类的`std::vector<Graph*>`改为`std::vector<Graph>`,会发生“对象切片”,派生类对象的特有部分被截断,只能存储基类对象,多态功能会完全丢失。

(3)若`~Graph()`未声明为虚函数,通过基类指针删除派生类对象时,仅会调用基类析构函数,派生类的资源无法被正确释放,会造成内存泄漏。


 问题3:扩展性思考
新增星形Star需在以下文件做改动:
1. 在Graph.hpp中:
- 在`enum class GraphType`中添加`star`枚举值;
- 新增`Star`类的声明,使其继承自`Graph`。

2. 在Graph.cpp中:
- 实现`Star`类的`draw`函数;
- 在`str_to_GraphType`函数中添加对“star”字符串的处理;
- 在`make_graph`函数的switch语句中,添加`case GraphType::star`的分支,返回新的`Star`对象。


问题4:资源管理
(1)`make_graph`返回的对象,是在Canvas类的析构函数中被释放的。

(2)使用原始指针管理内存的利弊:
利:
- 使用方式简单直接;
- 可明确管理内存生命周期,对指针的控制更精确。

弊:
- 容易忘记释放内存,导致内存泄漏;
- 可能出现重复释放同一块内存的问题。

任务四

代码

 1 #pragma once
 2 #include <string>
 3 #include <iostream>
 4 #include <vector>
 5 
 6 class Toy {
 7 protected:
 8     std::string name_;      // 三丽鸥玩具名称(含角色昵称)
 9     std::string type_;      // 玩具类型(贴合角色特色)
10     double price_;          // 玩具价格(符合三丽鸥周边定价)
11     std::string material_;  // 材质(精致感适配三丽鸥产品)
12     std::string brand_;     // 品牌固定为"三丽鸥(Sanrio)"
13     std::string ageRange_;  // 适用年龄(三丽鸥核心受众)
14 
15 public:
16     Toy(const std::string& name, const std::string& type, double price,
17         const std::string& material, const std::string& brand, const std::string& ageRange)
18         : name_(name), type_(type), price_(price), material_(material),
19           brand_(brand), ageRange_(ageRange) {}
20 
21     virtual void specialAbility() const = 0;
22     virtual void displayInfo() const;
23     virtual ~Toy() = default;
24 
25     std::string getName() const { return name_; }
26     std::string getType() const { return type_; }
27     double getPrice() const { return price_; }
28 };
29 
30 // Hello Kitty音乐盒(三丽鸥经典角色:Hello Kitty)
31 class HelloKittyMusicBox : public Toy {
32 public:
33     HelloKittyMusicBox(const std::string& name, double price, const std::string& material, const std::string& ageRange)
34         : Toy(name, "Hello Kitty主题音乐盒", price, material, "三丽鸥(Sanrio)", ageRange) {}
35 
36     void specialAbility() const override;
37 };
38 
39 // My Melody夜灯(三丽鸥角色:美乐蒂)
40 class MyMelodyLamp : public Toy {
41 public:
42     MyMelodyLamp(const std::string& name, double price, const std::string& material, const std::string& ageRange)
43         : Toy(name, "My Melody感应夜灯", price, material, "三丽鸥(Sanrio)", ageRange) {}
44 
45     void specialAbility() const override;
46 };
47 
48 // Kuromi互动玩偶(三丽鸥角色:库洛米)
49 class KuromiDoll : public Toy {
50 public:
51     KuromiDoll(const std::string& name, double price, const std::string& material, const std::string& ageRange)
52         : Toy(name, "Kuromi语音互动玩偶", price, material, "三丽鸥(Sanrio)", ageRange) {}
53 
54     void specialAbility() const override;
55 };
56 
57 // Cinnamoroll毛绒玩具(三丽鸥角色:玉桂狗)
58 class CinnamorollPlush : public Toy {
59 public:
60     CinnamorollPlush(const std::string& name, double price, const std::string& material, const std::string& ageRange)
61         : Toy(name, "Cinnamoroll软萌毛绒玩具", price, material, "三丽鸥(Sanrio)", ageRange) {}
62 
63     void specialAbility() const override;
64 };
65 
66 class ToyFactory {
67 private:
68     std::vector<Toy*> toys_;
69 
70 public:
71     ToyFactory() = default;
72     ~ToyFactory();
73 
74     void addToy(Toy* toy);
75     void displayAllToys() const;
76     void tryAllAbilities() const;
77 };
Toy.hpp
 1 #include "Toy.hpp"
 2 #include <iomanip>
 3 
 4 void Toy::displayInfo() const {
 5     std::cout << std::fixed << std::setprecision(2);
 6     std::cout << "【三丽鸥玩具信息】" << std::endl;
 7     std::cout << "名称: " << name_ << "\t类型: " << type_ << "\t价格: ¥" << price_ << std::endl;
 8     std::cout << "材质: " << material_ << "\t品牌: " << brand_ << "\t适用年龄: " << ageRange_ << "\n" << std::endl;
 9 }
10 
11 // Hello Kitty音乐盒功能:播放三丽鸥经典旋律
12 void HelloKittyMusicBox::specialAbility() const {
13     std::cout << "[Hello Kitty-" << name_ << "] 启动功能: 打开顶盖自动播放《Hello Kitty主题曲》, Kitty耳朵随旋律轻晃~\n" << std::endl;
14 }
15 
16 // My Melody夜灯功能:感应亮灯+渐变光效
17 void MyMelodyLamp::specialAbility() const {
18     std::cout << "[My Melody-" << name_ << "] 启动功能: 手靠近自动亮灯,支持粉/白/浅紫三色渐变,睡前模式10分钟后自动熄灭~\n" << std::endl;
19 }
20 
21 // Kuromi互动玩偶功能:语音对话+录音变声
22 void KuromiDoll::specialAbility() const {
23     std::cout << "[Kuromi-" << name_ << "] 启动功能: 按压头顶说'Kuromi'会回应'嘿!要和我一起捣蛋吗~',还能录下你的声音变声成可爱语调~\n" << std::endl;
24 }
25 
26 // Cinnamoroll毛绒玩具功能:触摸发声+柔软震动
27 void CinnamorollPlush::specialAbility() const {
28     std::cout << "[Cinnamoroll-" << name_ << "] 启动功能: 摸肚子发出'汪汪~'软萌叫声,抱紧时会轻轻震动,模拟撒娇动作~\n" << std::endl;
29 }
30 
31 ToyFactory::~ToyFactory() {
32     for (Toy* toy : toys_) {
33         delete toy;
34     }
35     toys_.clear();
36 }
37 
38 void ToyFactory::addToy(Toy* toy) {
39     if (toy != nullptr) {
40         toys_.push_back(toy);
41     }
42 }
43 
44 void ToyFactory::displayAllToys() const {
45     std::cout << "==================================== 三丽鸥玩具工厂产品清单 ====================================\n" << std::endl;
46     if (toys_.empty()) {
47         std::cout << "当前工厂暂无三丽鸥玩具产品!" << std::endl;
48         return;
49     }
50     for (const Toy* toy : toys_) {
51         toy->displayInfo();
52     }
53 }
54 
55 void ToyFactory::tryAllAbilities() const {
56     std::cout << "==================================== 三丽鸥玩具特异功能测试 ====================================\n" << std::endl;
57     if (toys_.empty()) {
58         std::cout << "当前工厂暂无三丽鸥玩具,无法测试功能!" << std::endl;
59         return;
60     }
61     for (const Toy* toy : toys_) {
62         toy->specialAbility();
63     }
64 }
Toy.cpp
 1 #include "Toy.hpp"
 2 
 3 void testSanrioToySystem() {
 4     ToyFactory sanrioFactory;
 5 
 6     // 添加三丽鸥经典角色玩具
 7     sanrioFactory.addToy(new HelloKittyMusicBox("Kitty酱", 299.99, "ABS树脂+亚克力", "3-12岁"));
 8     sanrioFactory.addToy(new MyMelodyLamp("Melody甜", 189.80, "硅胶+PC透明壳", "2-10岁"));
 9     sanrioFactory.addToy(new KuromiDoll("Kuromi酷", 349.00, "短绒布+硅胶", "4-14岁"));
10     sanrioFactory.addToy(new CinnamorollPlush("Cinnamoroll软", 259.99, "云朵绒+PP棉", "2-11岁"));
11     sanrioFactory.addToy(new HelloKittyMusicBox("Kitty甜", 319.99, "实木+水晶", "5-15岁"));
12 
13     // 展示产品+测试功能
14     sanrioFactory.displayAllToys();
15     sanrioFactory.tryAllAbilities();
16 }
17 
18 int main() {
19     testSanrioToySystem();
20     return 0;
21 }
task4.cpp

效果

a0abc8f3fb696c2e34c03f6aa30b5218

 

411ce9a33039087eaba5019c9107e06c

 

posted @ 2025-12-01 23:36  duser  阅读(0)  评论(0)    收藏  举报