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

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

回答问题:
问题1:继承关系识别 写出GradeCalc类声明体现"继承"关系的完整代码行。
class GradeCalc: private std::vector //继承标准库中的接口vector
问题2:接口暴露理解 当前继承方式下,基类vector的接口会自动成为GradeCalc的接口吗? 如在test模块中这样用,能否编译通过?用一句话解释原因。
GradeCalc c("OOP");
c.input(5);
c.push_back(97); // 合法吗?
不会成为GradeCalc的接口,编译不通过;原因:GradeCalc 采用私有继承 vector<int>,vector<int>中的接口(如push_back等)会被隐藏,外部无法直接调用。
问题3:数据访问差异
对比继承方式与组合方式内部实现数据访问的一行典型代码。说明两种方式下的封装差异带来的数据访问接口差异。
// 组合方式 for(auto grade: grades) //通过私有成员变量直接访问数据。
// 继承方式 for(int grade: *this) //通过 this 指针访问数据。
差异:组合是 “has-a” 关系,数据访问受类接口限制;继承是 “is-a” 关系,子类可直接访问基类数据。综合来看,组合方式封装性更强。
问题4:组合 vs. 继承方案选择 你认为组合方案和继承方案,哪个更适合成绩计算这个问题场景?简洁陈述你的结论和理由。
组合更合适;理由:从数据访问差异等方面来看,明显组合的封装性更好,存储的数据更为安全。且组合更具有灵活性,增添相关功能时更方便,而继承局限于“is-a”的关系。
实验任务三:
源代码:
1 #pragma once 2 #include <string> 3 #include <vector> 4 5 enum class GraphType { circle, triangle, rectangle }; 6 // Graph类定义 7 class Graph { 8 public: 9 virtual void draw() {} 10 virtual ~Graph() = default; 11 }; 12 // Circle类声明 13 class Circle : public Graph { 14 public: 15 void draw(); 16 }; 17 // Triangle类声明 18 class Triangle : public Graph { 19 public: 20 void draw(); 21 }; 22 // Rectangle类声明 23 class Rectangle : public Graph { 24 public: 25 void draw(); 26 }; 27 // Canvas类声明 28 class Canvas { 29 public: 30 void add(const std::string& type); // 根据字符串添加图形 31 void paint() const; 32 ~Canvas(); 33 private: 34 std::vector<Graph*> graphs; 35 }; 36 // 使用统一接口绘制所有图形 37 // 手动释放资源 38 // 4. 工具函数 39 GraphType str_to_GraphType(const std::string& s); // 字符串转枚举类型 40 Graph* make_graph(const std::string& type); // 创建图形,返回堆对象指针
1 #include <algorithm> 2 #include <cctype> 3 #include <iostream> 4 #include <string> 5 #include "Graph.hpp" 6 // Circle类实现 7 void Circle::draw() 8 { 9 std::cout << "draw a circle...\n"; 10 } 11 // Triangle类实现 12 void Triangle::draw() { std::cout << "draw a triangle...\n"; } 13 // Rectangle类实现 14 void Rectangle::draw() { std::cout << "draw a rectangle...\n"; } 15 // Canvas类实现 16 void Canvas::add(const std::string& type) { 17 Graph* g = make_graph(type); 18 if (g) 19 graphs.push_back(g); 20 } 21 void Canvas::paint() const { 22 for (Graph* g : graphs) 23 g->draw(); 24 } 25 Canvas::~Canvas() { 26 for (Graph* g : graphs) 27 delete g; 28 } 29 // 工具函数实现 30 // 字符串 → 枚举转换 31 GraphType str_to_GraphType(const std::string& s) { 32 std::string t = s; 33 std::transform(s.begin(), s.end(), t.begin(), 34 [](unsigned char c) { return std::tolower(c);}); 35 if (t == "circle") 36 return GraphType::circle; 37 if (t == "triangle") 38 return GraphType::triangle; 39 if (t == "rectangle") 40 return GraphType::rectangle; 41 return GraphType::circle; // 缺省返回 42 } 43 // 创建图形,返回堆对象指针 44 Graph* make_graph(const std::string& type) { 45 switch (str_to_GraphType(type)) { 46 case GraphType::circle: return new Circle; 47 case GraphType::triangle: return new Triangle; 48 case GraphType::rectangle: return new Rectangle; 49 default: return nullptr; 50 } 51 }
1 #include <string> 2 #include "Graph.hpp" 3 void test() { 4 Canvas canvas; 5 canvas.add("circle"); 6 canvas.add("triangle"); 7 canvas.add("rectangle"); 8 canvas.paint(); 9 } 10 int main() { 11 test(); 12 }
运行结果截图:

问题1:对象关系识别
(1)写出Graph.hpp中体现"组合"关系的成员声明代码行,并用一句话说明被组合对象的功能。
std::vector<Graph*> graphs; 用vector容器存储指向Graph类型的指针,便于实行增删改查等操作。
(2)写出Graph.hpp中体现"继承"关系的类声明代码行。
class Circle : public Graph
class Triangle : public Graph
class Rectangle : public Graph
问题2:多态机制观察
(1)Graph中的draw若未声明成虚函数,Canvas::paint()中g->draw()运行结果会有何不同?
所有调用都会执行基类 Graph 的 draw () 函数(无输出或默认输出),失去多态特性,无法调用子类的具体绘制实现。
(2)若Canvas类std::vector<Graph*>改成std::vector<Graph>,会出现什么问题?
会发生“对象切片”,即:对象存储到 vector<Graph>时,仅保留基类部分数据,子类特有成员丢失,调用 draw () 时也仅会执行基类逻辑。
(3)若~Graph()未声明成虚函数,会带来什么问题?
内存会泄漏;删除 Graph * 指针时,仅调用基类析构函数,子类对象所占用的内存无法释放(子类析构函数不会执行)。
问题3:扩展性思考 若要新增星形Star,需在哪些文件做哪些改动?逐一列出。
Graph.hpp:
增加GraphType枚举: enum class GraphType {circle, triangle, rectangle, star}
新增Star类:class Star : public Graph { public: void draw() ; }
Graph.cpp:
void Star::draw(){ std::cout << "draw a star...\n";}
定义 str_to_GraphType 函数:if (t == "star") return GraphType::star;
定义 make_graph 函数:case GraphType::star: return new Star;
问题4:资源管理 观察make_graph函数和Canvas析构函数:
(1)make_graph返回的对象在什么地方被释放?
make_graph 返回的对象在 Canvas 类的析构函数中被释放。
(2)使用原始指针管理内存有何利弊?
利:灵活性高,可动态管理不同类型的对象,直接控制对象的创建和释放时机。
弊:可能出现内存泄漏的现象,以及出现“野指针”,手动管理成本高。
实验任务四:
问题描述:设计一套电子毛绒玩具管理系统,支持多种玩具(如bear、rabbit、bird等),通过玩具工厂类统一管理所有玩具,提供展示所有玩具信息,通过价格排序以及通过产地查找玩具的接口,支持添加新玩具。
对象关系:
继承关系:Toy(基类)→ BearToy(子类)、RabbitToy(子类)、BirdToy(子类)。理由:所有玩具都具有基础属性(名称、类型、产地、价格)和特有属性(特异功能),子类通过继承基类获得基础属性和接口,并实现特异功能实现。
组合关系:ToyFactory(工厂类)→ std::vector<Toy*>(玩具)。理由:工厂 “包含” 多个玩具,便于统一集中管理玩具,同时vector还提供多种接口便于使用,可以有效减少代码量,让代码更为简洁。也符合 “has-a” 关系。
源代码:
1 #pragma once 2 #include<vector> 3 #include<string> 4 5 using std::string; 6 using std::vector; 7 8 //enum class ToyType{ bear,rabbit,bird}; 9 class Toy { 10 public: 11 Toy(const string& name_, const string& type_,const string& source_, double price_); 12 13 virtual ~Toy() = default; 14 virtual void Info() const; // 展示玩具基础信息 15 virtual bool is_money_enough(double money) const; //判断钱是否够买 16 virtual void show_specialfunction() const=0; //展示特异功能 17 virtual string& get_source() ; //得到产地 18 virtual string& get_name(); //得到名称 19 virtual double get_price(); //得到价格 20 private: 21 string name; //玩具名称 22 string type; //玩具类型 23 string source; //玩具产地 24 25 double price; //玩具价格 26 27 }; 28 29 class BearToy :public Toy { 30 public: 31 BearToy(const string& name_, const string& type_, const string& source_, double price_ ,const string& specialfunction_); 32 void show_specialfunction() const; //展示特异功能 33 private: 34 string specialfunction; // 35 }; 36 37 class RabbitToy :public Toy { 38 public: 39 RabbitToy(const string& name_, const string& type_, const string& source_, double price_, const string& specialfunction_); 40 void show_specialfunction() const; //展示特异功能 41 private: 42 string specialfunction; // 43 }; 44 45 class BirdToy :public Toy { 46 public: 47 BirdToy(const string& name_, const string& type_, const string& source_, double price_, const string& specialfunction_); 48 void show_specialfunction() const; //展示特异功能 49 private: 50 string specialfunction; 51 }; 52 53 class ToyFactory { 54 public: 55 ~ToyFactory(); 56 void add_toy(Toy* toy); // 添加玩具 57 void display() const; // 展示所有玩具信 58 void find_toy(const string source) const ; //由产地溯源 59 void sort_price() ; //价格升序排列 60 private: 61 vector<Toy*> toys; // 存储所有玩具 62 };
1 #pragma once 2 #include<iostream> 3 #include<string> 4 #include<vector> 5 #include<algorithm> 6 #include"Toy.hpp" 7 using namespace std; 8 ; 9 10 Toy::Toy(const string& name_, const string& type_, const string& source_, double price_) : 11 name{ name_ }, type{ type_ }, source{ source_ }, price{ price_ } {} 12 13 void Toy::Info()const { 14 cout << "玩具名称:" << name << '\n' 15 << "玩具类型:" << type << '\n' 16 << "玩具产地:" << source << '\n' 17 << "玩具价格:" << price << "元\n"; 18 } 19 20 bool Toy::is_money_enough(double money)const{ 21 return money >= price; 22 } 23 string& Toy::get_source() { 24 return source; 25 } 26 string& Toy::get_name() { 27 return name; 28 } 29 double Toy::get_price() { 30 return price; 31 } 32 BearToy::BearToy(const string& name_, const string& type_, const string& source_, double price_, const string& specialfunction_): 33 Toy(name_,type_,source_,price_),specialfunction{specialfunction_}{ } 34 void BearToy::show_specialfunction() const { 35 cout << "*特异功能:" << specialfunction<<'\n'; 36 } 37 RabbitToy::RabbitToy(const string& name_, const string& type_, const string& source_, double price_, const string& specialfunction_) : 38 Toy(name_, type_, source_, price_), specialfunction{ specialfunction_ } { 39 } 40 void RabbitToy::show_specialfunction() const { 41 cout << "*特异功能:" << specialfunction << '\n'; 42 } 43 44 BirdToy::BirdToy(const string& name_, const string& type_, const string& source_, double price_, const string& specialfunction_) : 45 Toy(name_, type_, source_, price_), specialfunction{ specialfunction_ } { 46 } 47 void BirdToy::show_specialfunction() const { 48 cout << "*特异功能:" << specialfunction << '\n'; 49 } 50 51 ToyFactory::~ToyFactory() { 52 for (Toy* toy : toys) { 53 delete toy; 54 } 55 } 56 57 void ToyFactory::add_toy(Toy* toy){ 58 if (toy) { 59 toys.push_back(toy); 60 } 61 } 62 void ToyFactory::display() const{ 63 cout << "---------------玩具工厂所有玩具信息 -----------------\n"; 64 if (toys.empty()) { 65 cout << "工厂内没有玩具。\n"; 66 return; 67 } 68 for (auto t : toys) { 69 t->Info(); 70 t->show_specialfunction(); 71 cout << '\n'; 72 } 73 cout << "-----------------------------------------------------\n"; 74 75 } 76 void ToyFactory::find_toy(const string place) const{ 77 string res; 78 int flag=0; 79 if (toys.empty()) { 80 cout<<"工厂为空,无法查找\n"; 81 return ; 82 } 83 for (auto t : toys) { 84 if (t->get_source() == place) { 85 res += t->get_name(); 86 res += '\n'; 87 flag = 1; 88 } 89 } 90 if (flag == 0) cout << "没有产自"<<place<<"的玩具\n"; 91 else cout << "产自" << place << "的有:\n" << res; 92 } 93 void ToyFactory::sort_price() { 94 sort(toys.begin(), toys.end(), [](auto a, auto b) {return a->get_price() < b->get_price();}); 95 }
1 #include "Toy.hpp" 2 #include <iostream> 3 4 ToyFactory factory; // 工厂类 5 void test1() { // 测试函数 6 7 // 调用工厂接口添加玩具 8 factory.add_toy(new BearToy("毛绒小熊", "经典","南京", 199.9,"当吉祥物")); 9 factory.add_toy(new RabbitToy("电动兔", "复古","南京", 69.9, "可以跑,但需要充电")); 10 factory.add_toy(new BirdToy("智能鸟", "智能","北京", 99.9, "像人一样说话")); 11 12 factory.display(); // 调用工厂接口展示所有玩具 13 14 factory.find_toy("南京"); 15 factory.sort_price(); 16 std::cout << "\n排序后:\n"; 17 factory.display(); 18 } 19 20 21 int main() { 22 test1(); 23 return 0; 24 }
运行结果截图:


浙公网安备 33010602011771号