实验四
实验四
任务一:
代码部分:
#pragma once #include <vector> #include <array> #include <string> class GradeCalc { public: GradeCalc(const std::string &cname); void input(int n); // 录入n个成绩 void output() const; // 输出成绩 void sort(bool ascending = false); // 排序 (默认降序) int min() const; // 返回最低分(如成绩未录入,返回-1) int max() const; // 返回最高分 (如成绩未录入,返回-1) double average() const; // 返回平均分 (如成绩未录入,返回0.0) void info(); // 输出课程成绩信息 private: void compute(); // 成绩统计 private: std::string course_name; // 课程名 std::vector<int> grades; // 课程成绩 std::array<int, 5> counts; // 保存各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100] std::array<double, 5> rates; // 保存各分数段人数占比 bool is_dirty; // 脏标记,记录是否成绩信息有变更 };
#include <algorithm> #include <array> #include <cstdlib> #include <iomanip> #include <iostream> #include <numeric> #include <string> #include <vector> #include "GradeCalc.hpp" GradeCalc::GradeCalc(const std::string &cname):course_name{cname},is_dirty{true} { counts.fill(0); rates.fill(0); } void GradeCalc::input(int n) { if(n < 0) { std::cerr << "无效输入! 人数不能为负数\n"; std::exit(1); } grades.reserve(n); int grade; for(int i = 0; i < n;) { std::cin >> grade; if(grade < 0 || grade > 100) { std::cerr << "无效输入! 分数须在[0,100]\n"; continue; } grades.push_back(grade); ++i; } is_dirty = true; // 设置脏标记:成绩信息有变更 } void GradeCalc::output() const { for(auto grade: grades) std::cout << grade << ' '; std::cout << std::endl; } void GradeCalc::sort(bool ascending) { if(ascending) std::sort(grades.begin(), grades.end()); else std::sort(grades.begin(), grades.end(), std::greater<int>()); } int GradeCalc::min() const { if(grades.empty()) return -1; auto it = std::min_element(grades.begin(), grades.end()); return *it; } int GradeCalc::max() const { if(grades.empty()) return -1; auto it = std::max_element(grades.begin(), grades.end()); return *it; } double GradeCalc::average() const { if(grades.empty()) return 0.0; double avg = std::accumulate(grades.begin(), grades.end(), 0.0)/grades.size(); return avg; } void GradeCalc::info() { if(is_dirty) compute(); std::cout << "课程名称:\t" << course_name << std::endl; std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl; std::cout << "最高分:\t" << max() << std::endl; std::cout << "最低分:\t" << min() << std::endl; const std::array<std::string, 5> grade_range{"[0, 60) ", "[60, 70)", "[70, 80)", "[80, 90)", "[90, 100]"}; for(int i = static_cast<int>(grade_range.size())-1; i >= 0; --i) std::cout << grade_range[i] << "\t: " << counts[i] << "人\t" << std::fixed << std::setprecision(2) << rates[i]*100 << "%\n"; } void GradeCalc::compute() { if(grades.empty()) return; counts.fill(0); rates.fill(0.0); // 统计各分数段人数 for(auto grade:grades) { if(grade < 60) ++counts[0]; // [0, 60) else if (grade < 70) ++counts[1]; // [60, 70) else if (grade < 80) ++counts[2]; // [70, 80) else if (grade < 90) ++counts[3]; // [80, 90) else ++counts[4]; // [90, 100] } // 统计各分数段比例 for(size_t i = 0; i < rates.size(); ++i) rates[i] = counts[i] * 1.0 / grades.size(); is_dirty = false; // 更新脏标记 }
#include <iostream> #include <string> #include "GradeCalc.hpp" void test() { GradeCalc c1("OOP"); std::cout << "录入成绩:\n"; c1.input(5); std::cout << "输出成绩:\n"; c1.output(); std::cout << "排序后成绩:\n"; c1.sort(); c1.output(); std::cout << "*************成绩统计信息*************\n"; c1.info(); } int main() { test(); }
结果截图:

问题回答:
问题1:
//GradeCalc 类声明中,组合关系的成员声明 std::string course_name; // 作用是存储课程名 std::vector<int> grades; // 动态存储课程成绩 std::array<int, 5> counts; // 静态存储各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100] std::array<double, 5> rates; // 静态存储各分数段人数占比
问题2:
不合法,c.push_back(97);在GradeCalc类中没有声明公有成员函数push_back,没有声明无法调用
问题3:
(1)compute只会调用第一次后面两次会跳过,is_dirty 避免重复计算相同的统计信息。当成绩数据未变化时,直接使用缓存结果,使得只有程序变化时,才会重新统计计算成绩
(2)不需要更改 compute()的调用位置,对于新增的update_grade(index, new_grade)只需要和之前一样在方法内部更新grades向量中的成绩,并且设置is_dirty =true,从而做到不直接调用compute()
问题4:
可以新增一个公有函数(中位数的)然后在GradeCalc.cpp添加中位数计算,最后就可以在测试中调用中位数函数了:
double GradeCalc::median() const { // 边界情况:空成绩表 if (grades为空) { return 0.0; } // 创建成绩副本 复制 grades 到 temp_grades; // 排序副本 对 temp_grades 进行升序排序; // 计算中位数 size_t n = temp_grades.size(); if (n 是奇数) { // 中位数 = 中间元素 return temp_grades[n/2]; } else { // 中位数 = 中间两个元素的平均值 int mid1 = temp_grades[n/2 - 1]; int mid2 = temp_grades[n/2]; return (mid1 + mid2) / 2.0; } }
问题5:
不能去掉,如果去掉在成绩变动(包括成绩修改,删减重新录入)的情况下会出错
问题6:
(1)程序功能没有影响,结果如图:
(2)性能有影响,去掉grades.reserve(n);会导致push_back()在成绩录入过程中触发多次内存重新分配和数据拷贝,显著降低程序性能
任务二:
代码部分:
#include <algorithm> #include <array> #include <cstdlib> #include <iomanip> #include <iostream> #include <numeric> #include <string> #include <vector> #include "GradeCalc.hpp" GradeCalc::GradeCalc(const std::string &cname): course_name{cname}, is_dirty{true}{ counts.fill(0); rates.fill(0); } void GradeCalc::input(int n) { if(n < 0) { std::cerr << "无效输入! 人数不能为负数\n"; return; } this->reserve(n); int grade; for(int i = 0; i < n;) { std::cin >> grade; if(grade < 0 || grade > 100) { std::cerr << "无效输入! 分数须在[0,100]\n"; continue; } this->push_back(grade); ++i; } is_dirty = true; } void GradeCalc::output() const { for(auto grade: *this) std::cout << grade << ' '; std::cout << std::endl; } void GradeCalc::sort(bool ascending) { if(ascending) std::sort(this->begin(), this->end()); else std::sort(this->begin(), this->end(), std::greater<int>()); } int GradeCalc::min() const { if(this->empty()) return -1; return *std::min_element(this->begin(), this->end()); } int GradeCalc::max() const { if(this->empty()) return -1; return *std::max_element(this->begin(), this->end()); } double GradeCalc::average() const { if(this->empty()) return 0.0; double avg = std::accumulate(this->begin(), this->end(), 0.0) / this->size(); return avg; } void GradeCalc::info() { if(is_dirty) compute(); std::cout << "课程名称:\t" << course_name << std::endl; std::cout << "平均分:\t" << std::fixed << std::setprecision(2) << average() << std::endl; std::cout << "最高分:\t" << max() << std::endl; std::cout << "最低分:\t" << min() << std::endl; const std::array<std::string, 5> grade_range{"[0, 60) ", "[60, 70)", "[70, 80)", "[80, 90)", "[90, 100]"}; for(int i = static_cast<int>(grade_range.size())-1; i >= 0; --i) std::cout << grade_range[i] << "\t: " << counts[i] << "人\t" << std::fixed << std::setprecision(2) << rates[i]*100 << "%\n"; } void GradeCalc::compute() { if(this->empty()) return; counts.fill(0); rates.fill(0); // 统计各分数段人数 for(int grade: *this) { if(grade < 60) ++counts[0]; // [0, 60) else if (grade < 70) ++counts[1]; // [60, 70) else if (grade < 80) ++counts[2]; // [70, 80) else if (grade < 90) ++counts[3]; // [80, 90) else ++counts[4]; // [90, 100] } // 统计各分数段比例 for(size_t i = 0; i < rates.size(); ++i) rates[i] = counts[i] * 1.0 / this->size(); is_dirty = false; }
#pragma once #include <array> #include <string> #include <vector> class GradeCalc: private std::vector<int> { public: GradeCalc(const std::string &cname); void input(int n); // 录入n个成绩 void output() const; // 输出成绩 void sort(bool ascending = false); // 排序 (默认降序) int min() const; // 返回最低分 int max() const; // 返回最高分 double average() const; // 返回平均分 void info(); // 输出成绩统计信息 private: void compute(); // 计算成绩统计信息 private: std::string course_name; // 课程名 std::array<int, 5> counts; // 保存各分数段人数([0, 60), [60, 70), [70, 80), [80, 90), [90, 100] std::array<double, 5> rates; // 保存各分数段占比 bool is_dirty; // 脏标记,记录是否成绩信息有变更 };
#include <iostream> #include <string> #include "GradeCalc.hpp" void test() { GradeCalc c1("OOP"); std::cout << "录入成绩:\n"; c1.input(5); std::cout << "输出成绩:\n"; c1.output(); std::cout << "排序后成绩:\n"; c1.sort(); c1.output(); std::cout << "*************成绩统计信息*************\n"; c1.info(); } int main() { test(); }
结果截图:

问题回答:
问题1:
class GradeCalc: private std::vector<int> {
问题2:
不能编译通过,因为私有继承使基类的公有成员在派生类中变为私有,外部代码无法直接访问
问题3:
组合方式提供细粒度接口控制,可以只暴露必要的业务方法;继承方式接口控制粗糙,要么全隐藏要么全暴露,难以提供安全的业务接口
问题4:
成绩计算类应该组合vector作为数据成员(成绩计算"拥有"(has-a)一个成绩集合,而不是"是一种"(is-a)vector),而不是继承它,因为组合提供更好的封装、更清晰的语义和更高的灵活性
任务三:
代码部分:
#pragma once #include <string> #include <vector> enum class GraphType {circle, triangle, rectangle}; // Graph类定义 class Graph { public: virtual void draw() {} virtual ~Graph() = default; }; // Circle类声明 class Circle : public Graph { public: void draw(); }; // Triangle类声明 class Triangle : public Graph { public: void draw(); }; // Rectangle类声明 class Rectangle : public Graph { public: void draw(); }; // Canvas类声明 class Canvas { public: void add(const std::string& type); // 根据字符串添加图形 void paint() const; // 使用统一接口绘制所有图形 ~Canvas(); // 手动释放资源 private: std::vector<Graph*> graphs; }; // 4. 工具函数 GraphType str_to_GraphType(const std::string& s); // 字符串转枚举类型 Graph* make_graph(const std::string& type); // 创建图形,返回堆对象指针
#include <algorithm> #include <cctype> #include <iostream> #include <string> #include "Graph.hpp" // Circle类实现 void Circle::draw() { std::cout << "draw a circle...\n"; } // Triangle类实现 void Triangle::draw() { std::cout << "draw a triangle...\n"; } // Rectangle类实现 void Rectangle::draw() { std::cout << "draw a rectangle...\n"; } // Canvas类实现 void Canvas::add(const std::string& type) { Graph* g = make_graph(type); if (g) graphs.push_back(g); } void Canvas::paint() const { for (Graph* g : graphs) g->draw(); } Canvas::~Canvas() { for (Graph* g : graphs) delete g; } // 工具函数实现 // 字符串 → 枚举转换 GraphType str_to_GraphType(const std::string& s) { std::string t = s; std::transform(s.begin(), s.end(), t.begin(), [](unsigned char c) { return std::tolower(c);}); if (t == "circle") return GraphType::circle; if (t == "triangle") return GraphType::triangle; if (t == "rectangle") return GraphType::rectangle; return GraphType::circle; // 缺省返回 } // 创建图形,返回堆对象指针 Graph* make_graph(const std::string& type) { switch (str_to_GraphType(type)) { case GraphType::circle: return new Circle; case GraphType::triangle: return new Triangle; case GraphType::rectangle: return new Rectangle; default: return nullptr; } }
#include <string> #include "Graph.hpp" void test() { Canvas canvas; canvas.add("circle"); canvas.add("triangle"); canvas.add("rectangle"); canvas.paint(); } int main() { test(); }
结果截图:

问题回答:
问题1:
(1):vector容器用于存储和管理Graph指针
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() 运行结果会什么都不输出或者输出空行(没有虚函数时,g->draw() 执行静态绑定(编译时确定),无论g实际指向什么对象,都调用Graph ::draw()的空实现)
(2):若 Canvas 类 std::vector<Graph*> 改成 std::vector<Graph>会出现:
只复制了Graph基类部分,丢失了派生类的特有数据和方法
总是调用Graph::draw(),无法调用派生类的draw()
类型信息丢失
内存管理混乱
(3):若 ~Graph() 未声明成虚函数会:
可能只析构部分对象
~Circle() { delete[] buffer; } 可能永远不会被调用(只调用~Graph(),不调用~Circle())
问题3:
在Graph.hpp里:
// 修改1:在枚举类型中添加 Star enum class GraphType {circle, triangle, rectangle, star}; // 新增 star // 修改2:添加 Star 类声明 class Star : public Graph { // 新增类 public: void draw(); };
在Graph.cpp里:
// 修改3:实现 Star::draw() 函数 void Star::draw() { std::cout << "draw a star...\n"; // 新增实现 } // 修改4:在 str_to_GraphType() 中添加星形判断 GraphType str_to_GraphType(const std::string& s) { std::string t = s; std::transform(s.begin(), s.end(), t.begin(), [](unsigned char c) { return std::tolower(c);}); if (t == "circle") return GraphType::circle; if (t == "triangle") return GraphType::triangle; if (t == "rectangle") return GraphType::rectangle; if (t == "star") return GraphType::star; // 新增 return GraphType::circle; // 缺省返回 } // 修改5:在 make_graph() 中添加 Star 的创建分支 Graph* make_graph(const std::string& type) { switch (str_to_GraphType(type)) { case GraphType::circle: return new Circle; case GraphType::triangle: return new Triangle; case GraphType::rectangle: return new Rectangle; case GraphType::star: return new Star; // 新增 default: return nullptr; } }
问题4:
(1):
// Canvas::~Canvas() 释放所有对象 Canvas::~Canvas() { for (Graph* g : graphs) delete g; // 在这里被释放
(2):
使用原始指针管理内存的好处:
对比智能指针无额外运行开销
原始指针可以精细准确控制内存管理
使用原始指针管理内存的坏处:
可能存在内存泄漏(忘记delete,没释放内存)或者出现重复释放内存
对异常不安全(没办法处理异常)
任务四:
代码部分:
Toy.hpp:
#pragma once #include <string> #include <memory> #include <vector> // 玩具类型枚举 enum class ToyType { SOUND, // 发声玩具 LIGHT, // 发光玩具 MOTION, // 运动玩具 COMPOSITE // 复合功能玩具 }; // 电池类型 enum class BatteryType { AA, // 5号电池 AAA, // 7号电池 BUTTON, // 纽扣电池 RECHARGEABLE // 充电电池 }; // 抽象玩具基类 class Toy { public: Toy(const std::string& name, ToyType type, float price, int recommendedAge, BatteryType battery, int batteryCount); virtual ~Toy() = default; // 纯虚函数 - 特异功能演示 virtual void showSpecialFunction() const = 0; // 虚函数 - 可以有默认实现 virtual void turnOn() const; virtual void turnOff() const; // 普通成员函数 void displayInfo() const; void setBatteryLevel(int level); int getBatteryLevel() const; bool needsBatteryReplacement() const; // Getter方法 std::string getName() const; ToyType getType() const; float getPrice() const; int getRecommendedAge() const; protected: std::string name; ToyType type; float price; int recommendedAge; // 建议年龄 BatteryType batteryType; int batteryCount; int batteryLevel; // 电池电量百分比 }; // 发声玩具基类 class SoundToy : public Toy { public: SoundToy(const std::string& name, float price, int recommendedAge, BatteryType battery, int batteryCount, const std::string& soundType, int volumeLevel); void showSpecialFunction() const override; void adjustVolume(int level); protected: std::string soundType; int volumeLevel; }; // 发光玩具基类 class LightToy : public Toy { public: LightToy(const std::string& name, float price, int recommendedAge, BatteryType battery, int batteryCount, const std::string& lightColor, int brightness); void showSpecialFunction() const override; void changeLightColor(const std::string& color); protected: std::string lightColor; int brightness; }; // 运动玩具基类 class MotionToy : public Toy { public: MotionToy(const std::string& name, float price, int recommendedAge, BatteryType battery, int batteryCount, const std::string& motionType, int speed); void showSpecialFunction() const override; void setMotionSpeed(int speed); protected: std::string motionType; int speed; }; // 复合功能玩具 class CompositeToy : public Toy { public: CompositeToy(const std::string& name, float price, int recommendedAge, BatteryType battery, int batteryCount); void showSpecialFunction() const override; void addFunction(const std::string& function); private: std::vector<std::string> functions; }; // 具体玩具类 class SingingBear : public SoundToy { public: SingingBear(); void showSpecialFunction() const override; void singSong(const std::string& song) const; }; class TalkingRabbit : public SoundToy { public: TalkingRabbit(); void showSpecialFunction() const override; void tellStory(const std::string& story) const; }; class TwinkleCat : public LightToy { public: TwinkleCat(); void showSpecialFunction() const override; void twinklePattern(int pattern) const; }; class RainbowDog : public LightToy { public: RainbowDog(); void showSpecialFunction() const override; void rainbowEffect() const; }; class DancingPenguin : public MotionToy { public: DancingPenguin(); void showSpecialFunction() const override; void danceMove(const std::string& move) const; }; class JumpingMonkey : public MotionToy { public: JumpingMonkey(); void showSpecialFunction() const override; void jumpHeight(int height) const; }; // 智能玩具 - 复合功能 class SmartToy : public CompositeToy { public: SmartToy(); void showSpecialFunction() const override; void voiceCommand(const std::string& command) const; };
ToyFactory.hpp:
#pragma once #include "Toy.hpp" #include <vector> #include <memory> class ToyFactory { public: ToyFactory(); // 工厂方法 - 创建各种玩具 std::unique_ptr<Toy> createToy(const std::string& toyName) const; // 批量创建示例玩具 void createSampleToys(); // 显示所有玩具信息 void displayAllToys() const; // 演示所有玩具的特异功能 void demonstrateAllFunctions() const; // 按类型筛选玩具 void displayToysByType(ToyType type) const; // 电池管理 void checkBatteryStatus() const; void replaceBatteriesForAll(); // 查找玩具 Toy* findToyByName(const std::string& name) const; // 统计信息 void displayStatistics() const; private: std::vector<std::unique_ptr<Toy>> toys; // 私有工具函数 std::string toyTypeToString(ToyType type) const; std::string batteryTypeToString(BatteryType type) const; void displaySeparator() const; };
Toy.cpp:
#include "Toy.hpp" #include <iostream> #include <iomanip> #include <string> using namespace std; // ========== Toy 基类实现 ========== Toy::Toy(const string& name, ToyType type, float price, int recommendedAge, BatteryType battery, int batteryCount) : name(name), type(type), price(price), recommendedAge(recommendedAge), batteryType(battery), batteryCount(batteryCount), batteryLevel(100) {} void Toy::turnOn() const { cout << name << " 已开启!" << endl; } void Toy::turnOff() const { cout << name << " 已关闭。" << endl; } void Toy::displayInfo() const { cout << "\n=== 玩具信息 ===" << endl; cout << "名称: " << name << endl; cout << "类型: "; switch(type) { case ToyType::SOUND: cout << "发声玩具"; break; case ToyType::LIGHT: cout << "发光玩具"; break; case ToyType::MOTION: cout << "运动玩具"; break; case ToyType::COMPOSITE: cout << "复合功能玩具"; break; } cout << endl; cout << "价格: ¥" << fixed << setprecision(2) << price << endl; cout << "建议年龄: " << recommendedAge << "+" << endl; cout << "电池电量: " << batteryLevel << "%" << endl; } void Toy::setBatteryLevel(int level) { batteryLevel = (level < 0) ? 0 : ((level > 100) ? 100 : level); } int Toy::getBatteryLevel() const { return batteryLevel; } bool Toy::needsBatteryReplacement() const { return batteryLevel < 20; } string Toy::getName() const { return name; } ToyType Toy::getType() const { return type; } float Toy::getPrice() const { return price; } int Toy::getRecommendedAge() const { return recommendedAge; } // ========== SoundToy 实现 ========== SoundToy::SoundToy(const string& name, float price, int recommendedAge, BatteryType battery, int batteryCount, const string& soundType, int volumeLevel) : Toy(name, ToyType::SOUND, price, recommendedAge, battery, batteryCount), soundType(soundType), volumeLevel(volumeLevel) {} void SoundToy::showSpecialFunction() const { cout << getName() << " 发出 " << soundType << " 声音!" << endl; } void SoundToy::adjustVolume(int level) { volumeLevel = level; cout << getName() << " 音量调整为: " << volumeLevel << endl; } // ========== LightToy 实现 ========== LightToy::LightToy(const string& name, float price, int recommendedAge, BatteryType battery, int batteryCount, const string& lightColor, int brightness) : Toy(name, ToyType::LIGHT, price, recommendedAge, battery, batteryCount), lightColor(lightColor), brightness(brightness) {} void LightToy::showSpecialFunction() const { cout << getName() << " 发出 " << lightColor << " 光芒!" << endl; } void LightToy::changeLightColor(const string& color) { lightColor = color; cout << getName() << " 灯光颜色改为: " << lightColor << endl; } // ========== MotionToy 实现 ========== MotionToy::MotionToy(const string& name, float price, int recommendedAge, BatteryType battery, int batteryCount, const string& motionType, int speed) : Toy(name, ToyType::MOTION, price, recommendedAge, battery, batteryCount), motionType(motionType), speed(speed) {} void MotionToy::showSpecialFunction() const { cout << getName() << " 进行 " << motionType << " 运动!" << endl; } void MotionToy::setMotionSpeed(int speed) { this->speed = speed; cout << getName() << " 运动速度调整为: " << speed << endl; } CompositeToy::CompositeToy(const string& name, float price, int recommendedAge, BatteryType battery, int batteryCount) : Toy(name, ToyType::COMPOSITE, price, recommendedAge, battery, batteryCount) {} void CompositeToy::showSpecialFunction() const { cout << getName() << " 展示复合功能:" << endl; for (const auto& func : functions) { cout << " - " << func << endl; } } void CompositeToy::addFunction(const string& function) { functions.push_back(function); } // ========== 具体玩具实现 ========== SingingBear::SingingBear() : SoundToy("唱歌小熊", 129.99, 3, BatteryType::AA, 3, "悦耳的歌声", 80) {} void SingingBear::showSpecialFunction() const { SoundToy::showSpecialFunction(); cout << "? 小熊开始唱歌啦! ?" << endl; cout << "啦啦啦... 我是快乐的小熊..." << endl; } void SingingBear::singSong(const string& song) const { cout << "唱歌小熊正在演唱: " << song << endl; } TalkingRabbit::TalkingRabbit() : SoundToy("说话兔子", 89.99, 2, BatteryType::AAA, 2, "可爱的童声", 70) {} void TalkingRabbit::showSpecialFunction() const { SoundToy::showSpecialFunction(); cout << "兔子说:你好!我是小兔子!" << endl; cout << "今天天气真好呀!" << endl; } void TalkingRabbit::tellStory(const string& story) const { cout << "说话兔子讲故事: " << story << endl; } TwinkleCat::TwinkleCat() : LightToy("闪烁猫", 79.99, 3, BatteryType::BUTTON, 1, "彩色", 85) {} void TwinkleCat::showSpecialFunction() const { LightToy::showSpecialFunction(); cout << "? 猫咪的眼睛闪闪发光 ?" << endl; } void TwinkleCat::twinklePattern(int pattern) const { cout << "闪烁猫展示闪烁模式: " << pattern << endl; } RainbowDog::RainbowDog() : LightToy("彩虹狗", 119.99, 3, BatteryType::RECHARGEABLE, 1, "彩虹色", 90) {} void RainbowDog::showSpecialFunction() const { LightToy::showSpecialFunction(); cout << "?? 小狗发出彩虹光芒 ??" << endl; } void RainbowDog::rainbowEffect() const { cout << "彩虹狗展示彩虹效果!" << endl; } DancingPenguin::DancingPenguin() : MotionToy("跳舞企鹅", 159.99, 4, BatteryType::AA, 4, "舞蹈", 60) {} void DancingPenguin::showSpecialFunction() const { MotionToy::showSpecialFunction(); cout << "?? 企鹅开始跳舞啦!" << endl; cout << "左摇摇... 右摆摆... 转个圈!" << endl; } void DancingPenguin::danceMove(const string& move) const { cout << "跳舞企鹅展示舞步: " << move << endl; } JumpingMonkey::JumpingMonkey() : MotionToy("跳跃猴", 99.99, 4, BatteryType::AAA, 3, "跳跃", 80) {} void JumpingMonkey::showSpecialFunction() const { MotionToy::showSpecialFunction(); cout << "?? 猴子开始跳跃!" << endl; cout << "跳!跳!跳!" << endl; } void JumpingMonkey::jumpHeight(int height) const { cout << "跳跃猴跳跃高度: " << height << "厘米" << endl; } SmartToy::SmartToy() : CompositeToy("智能玩具", 199.99, 5, BatteryType::RECHARGEABLE, 1) { addFunction("语音交互"); addFunction("灯光效果"); addFunction("动作表演"); } void SmartToy::showSpecialFunction() const { CompositeToy::showSpecialFunction(); cout << "?? 智能玩具开始表演!" << endl; } void SmartToy::voiceCommand(const string& command) const { cout << "智能玩具响应语音命令: " << command << endl; }
ToyFactory.cpp:
#include "ToyFactory.hpp" #include "Toy.hpp" #include <iostream> #include <string> #include <memory> #include <vector> #include <algorithm> #include <numeric> #include <iomanip> ToyFactory::ToyFactory() { createSampleToys(); } std::unique_ptr<Toy> ToyFactory::createToy(const std::string& toyName) const { if (toyName == "SingingBear") { return std::make_unique<SingingBear>(); } else if (toyName == "TalkingRabbit") { return std::make_unique<TalkingRabbit>(); } else if (toyName == "TwinkleCat") { return std::make_unique<TwinkleCat>(); } else if (toyName == "RainbowDog") { return std::make_unique<RainbowDog>(); } else if (toyName == "DancingPenguin") { return std::make_unique<DancingPenguin>(); } else if (toyName == "JumpingMonkey") { return std::make_unique<JumpingMonkey>(); } else if (toyName == "SmartToy") { return std::make_unique<SmartToy>(); } return nullptr; } void ToyFactory::createSampleToys() { toys.clear(); // 创建各种类型的玩具 toys.push_back(std::make_unique<SingingBear>()); toys.push_back(std::make_unique<TalkingRabbit>()); toys.push_back(std::make_unique<TwinkleCat>()); toys.push_back(std::make_unique<RainbowDog>()); toys.push_back(std::make_unique<DancingPenguin>()); toys.push_back(std::make_unique<JumpingMonkey>()); toys.push_back(std::make_unique<SmartToy>()); // 设置不同的电池电量,模拟真实情况 toys[0]->setBatteryLevel(85); // 唱歌小熊 toys[1]->setBatteryLevel(45); // 说话兔子 toys[2]->setBatteryLevel(15); // 闪烁猫(需要换电池) toys[3]->setBatteryLevel(95); // 彩虹狗 toys[4]->setBatteryLevel(60); // 跳舞企鹅 toys[5]->setBatteryLevel(10); // 跳跃猴(需要换电池) toys[6]->setBatteryLevel(75); // 智能玩具 } void ToyFactory::displayAllToys() const { displaySeparator(); std::cout << "玩具工厂库存 (" << toys.size() << " 件玩具)" << std::endl; displaySeparator(); for (size_t i = 0; i < toys.size(); ++i) { std::cout << "\n[" << i + 1 << "] "; toys[i]->displayInfo(); } } void ToyFactory::demonstrateAllFunctions() const { displaySeparator(); std::cout << "演示所有玩具的特异功能" << std::endl; displaySeparator(); for (const auto& toy : toys) { std::cout << "\n★ " << toy->getName() << " ★" << std::endl; toy->turnOn(); toy->showSpecialFunction(); toy->turnOff(); } } void ToyFactory::displaySeparator() const { std::cout << std::string(50, '=') << std::endl; } std::string ToyFactory::toyTypeToString(ToyType type) const { switch (type) { case ToyType::SOUND: return "发声玩具"; case ToyType::LIGHT: return "发光玩具"; case ToyType::MOTION: return "运动玩具"; case ToyType::COMPOSITE: return "复合功能玩具"; default: return "未知类型"; } } std::string ToyFactory::batteryTypeToString(BatteryType type) const { switch (type) { case BatteryType::AA: return "5号电池"; case BatteryType::AAA: return "7号电池"; case BatteryType::BUTTON: return "纽扣电池"; case BatteryType::RECHARGEABLE: return "充电电池"; default: return "未知电池"; } } void ToyFactory::displayToysByType(ToyType type) const { displaySeparator(); std::cout << toyTypeToString(type) << "列表:" << std::endl; displaySeparator(); int count = 0; for (const auto& toy : toys) { if (toy->getType() == type) { std::cout << "\n[" << ++count << "] "; toy->displayInfo(); } } if (count == 0) { std::cout << "没有找到此类玩具。" << std::endl; } } void ToyFactory::checkBatteryStatus() const { displaySeparator(); std::cout << "电池状态检查" << std::endl; displaySeparator(); int lowBatteryCount = 0; for (const auto& toy : toys) { if (toy->needsBatteryReplacement()) { std::cout << "?? " << toy->getName() << " 电池电量低: " << toy->getBatteryLevel() << "%" << std::endl; lowBatteryCount++; } } if (lowBatteryCount == 0) { std::cout << "所有玩具电池电量充足!" << std::endl; } else { std::cout << "共有 " << lowBatteryCount << " 个玩具需要更换电池。" << std::endl; } } void ToyFactory::replaceBatteriesForAll() { for (auto& toy : toys) { toy->setBatteryLevel(100); } } Toy* ToyFactory::findToyByName(const std::string& name) const { for (const auto& toy : toys) { if (toy->getName() == name) { return toy.get(); } } return nullptr; } void ToyFactory::displayStatistics() const { displaySeparator(); std::cout << "玩具工厂统计信息" << std::endl; displaySeparator(); int soundCount = 0, lightCount = 0, motionCount = 0, compositeCount = 0; float totalValue = 0.0f; int totalBatteryLevel = 0; for (const auto& toy : toys) { totalValue += toy->getPrice(); totalBatteryLevel += toy->getBatteryLevel(); switch (toy->getType()) { case ToyType::SOUND: soundCount++; break; case ToyType::LIGHT: lightCount++; break; case ToyType::MOTION: motionCount++; break; case ToyType::COMPOSITE: compositeCount++; break; } } std::cout << "玩具总数: " << toys.size() << " 件" << std::endl; std::cout << "发声玩具: " << soundCount << " 件" << std::endl; std::cout << "发光玩具: " << lightCount << " 件" << std::endl; std::cout << "运动玩具: " << motionCount << " 件" << std::endl; std::cout << "复合功能玩具: " << compositeCount << " 件" << std::endl; std::cout << "总价值: ¥" << std::fixed << std::setprecision(2) << totalValue << std::endl; if (!toys.empty()) { std::cout << "平均电池电量: " << totalBatteryLevel / toys.size() << "%" << std::endl; } }
demo4.cpp :
#include "ToyFactory.hpp" #include <iostream> using namespace std; int main() { cout << "=== 毛绒玩具管理系统 ===" << endl; ToyFactory factory; cout << "\n1. 显示所有玩具:" << endl; factory.displayAllToys(); cout << "\n2. 演示功能:" << endl; factory.demonstrateAllFunctions(); cout << "\n3. 电池检查:" << endl; factory.checkBatteryStatus(); cout << "\n程序结束!" << endl; system("pause"); return 0; }
注:此处使用了智能指针,所以把c++版本调成了c++14
问题回答:
(1)问题描述:
现代毛绒玩具不再是简单的填充玩偶,而是集成了声、光、电、动等多种功能的智能玩具。不同类型的玩具具有不同的特异功能,包含了:
1、发声玩具:能唱歌、讲故事、模仿动物叫声
2、发光玩具:能发出彩色光芒、闪烁特效
3、运动玩具:能跳舞、跳跃、行走
4、复合玩具:集成多种功能的智能玩具
玩具厂商需要一套管理系统来进行统计和管理:
1、统一管理各种类型的电子毛绒玩具
2、展示每种玩具的特异功能
3、统计玩具库存信息
4、管理玩具的电池状态
对象关系:有两层,玩具工厂类与玩具类的组合关系,玩具类(成员包括了价格,名称,电量等)和派生类(具体玩具类型)的继承关系

浙公网安备 33010602011771号