实验4 组合与继承

1. 实验任务1
#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;      // 脏标记,记录是否成绩信息有变更
};
GradeCalc.hpp
#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;  // 更新脏标记
}
GradeCalc.cpp
#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();
}
task1.cpp

image

 问题1

  1. std::string course_name; - 存储课程名称

  2. std::vector<int> grades; - 存储学生成绩

  3. std::array<int, 5> counts; - 统计各分数段的人数

  4. std::array<double, 5> rates; - 存储各分数段的占比

问题2

不合法

grades是GradeCalc类的私有(private)成员,test函数无法直接访问私有成员

问题3

(1)1次

is_dirty避免重复计算

(2)不需要。只需在update_grade函数中将is_dirty设为true即可

问题4

info()函数中添加中位数统计,不新增数据成员

void GradeCalc::info() {
    if(is_dirty)
        compute();
    
    // 计算中位数
    double median = 0.0;
    if(!grades.empty()) {
        std::vector<int> sorted_grades = grades;  // 复制一份
        std::sort(sorted_grades.begin(), sorted_grades.end());
        
        int n = sorted_grades.size();
        if(n % 2 == 1) {
            median = sorted_grades[n/2];
        } else {
            median = (sorted_grades[n/2 - 1] + sorted_grades[n/2]) / 2.0;
        }
    }
    
    // 输出中位数
    std::cout << "中位数:\t" << std::fixed << std::setprecision(2) << median << std::endl;
    
    // 原有输出代码...
}
伪代码

问题5:

不能去掉

会引发错误的场景:

  1. 多次录入成绩时

  2. 更新成绩后重新计算时

  3. 清空成绩后重新录入时

问题6

(1)没有影响,程序仍然可以运行

(2)有;vector需要多次重新分配内存和拷贝数据,增加了运行时间开销

 

2. 实验任务2
#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;      // 脏标记,记录是否成绩信息有变更
};
GradeCalc.hpp
#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;
}
GradeCalc.cpp
#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();
}
task2.cpp

image

 问题1:

class GradeCalc: private std::vector<int> {

问题2

不会

不能编译通过

原因:私有继承使基类的公有成员在派生类中都变为私有成员,外部代码无法访问

问题3:

继承封装性差,组合封装性好

问题4

组合方案更合适

封装性更好,灵活性更高

 

3. 实验任务3
#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);  // 创建图形,返回堆对象指针
Graph.hpp
#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;
    }
}
Graph.cpp
#include <string>
#include "Graph.hpp"

void test() {
    Canvas canvas;

    canvas.add("circle");
    canvas.add("triangle");
    canvas.add("rectangle");
    canvas.paint();
}

int main() {
    test();
}
task3.cpp

image

 问题1:

(1)

private:
std::vector<Graph*> graphs;

用于存储指向各种图形对象的指针,实现Canvas对多个图形的"拥有"关系

(2)

class Circle : public Graph { ... };
class Triangle : public Graph { ... };
class Rectangle : public Graph { ... };

问题2

(1)输出结果将全部是:"draw a graph..."(如果Graph::draw有实现)或者什么都不输出(当前代码Graph::draw为空实现)

(2)Graph类可能没有合适的拷贝构造函数,程序无法运行

(3)派生类资源无法释放:如果派生类有自己的动态内存分配或其他资源

析构不完整:只执行基类析构,派生类析构被跳过

违反"基类析构应为虚函数"的原则:当类设计为多态基类时,析构函数应该声明为虚函数

问题3

1. Graph.hpp文件中:

(1)扩展枚举类型:

enum class GraphType {circle, triangle, rectangle, star};

(2)新增Star类声明:

class Star : public Graph {
public:
    void draw();
};

2. Graph.cpp文件中:

(1)实现Star::draw()方法:

void Star::draw() { std::cout << "draw a star...\n"; }

(2)扩展str_to_GraphType函数:

if (t == "star")
    return GraphType::star;

(3)扩展make_graph函数:

case GraphType::star: return new Star;

3. 测试文件(demo3.cpp)中:

canvas.add("star");  // 可以测试新增的图形

问题4
(1)
在Canvas的析构函数中释放
(2)
性能高,但是有内存泄漏风险


4. 实验任务4
#pragma once
#include <string>
#include <memory>

// 玩具类型枚举
enum class ToyType {
    TEDDY_BEAR,
    ROBOT_DOG,
    MUSIC_RABBIT,
    TALKING_BIRD
};

// 抽象基类:毛绒玩具
class Toy {
public:
    Toy(const std::string& name, ToyType type, float price);
    virtual ~Toy() = default;
    
    // 通用接口
    virtual void showInfo() const;
    virtual void play() = 0;  // 纯虚函数,特异功能
    
    // Getter方法
    std::string getName() const { return name_; }
    ToyType getType() const { return type_; }
    float getPrice() const { return price_; }
    int getBatteryLevel() const { return battery_level_; }
    
    // 通用功能
    void charge(int amount);
    void setVolume(int level);
    void sleep();
    void wakeUp();
    
protected:
    std::string name_;
    ToyType type_;
    float price_;
    int battery_level_;
    int volume_level_;
    bool is_awake_;
};

// 具体玩具类:泰迪熊
class TeddyBear : public Toy {
public:
    TeddyBear(const std::string& name, float price);
    void play() override;
    void hug();
    void tellStory();
    
private:
    int hug_count_;
};

// 具体玩具类:机器狗
class RobotDog : public Toy {
public:
    RobotDog(const std::string& name, float price);
    void play() override;
    void walk();
    void bark();
    void fetch();
    
private:
    int step_count_;
};

// 具体玩具类:音乐兔
class MusicRabbit : public Toy {
public:
    MusicRabbit(const std::string& name, float price);
    void play() override;
    void playMusic(int song_id);
    void dance();
    void recordMessage(const std::string& message);
    
private:
    std::vector<std::string> song_list_;
    std::string recorded_message_;
};

// 具体玩具类:会说话的鸟
class TalkingBird : public Toy {
public:
    TalkingBird(const std::string& name, float price);
    void play() override;
    void repeat(const std::string& phrase);
    void sing();
    void flyAnimation();
    
private:
    std::vector<std::string> learned_phrases_;
};
Toy.hpp
#pragma once
#include "Toy.hpp"
#include <vector>
#include <memory>

class ToyFactory {
public:
    ToyFactory();
    
    // 工厂方法:创建玩具
    std::shared_ptr<Toy> createToy(ToyType type, const std::string& name, float price);
    
    // 批量创建示例玩具
    void createSampleToys();
    
    // 显示所有玩具信息
    void showAllToys() const;
    
    // 按类型显示玩具
    void showToysByType(ToyType type) const;
    
    // 玩具操作
    void playWithToy(const std::string& name);
    void chargeAllToys();
    
    // 统计信息
    int getTotalToyCount() const;
    float getTotalValue() const;
    
private:
    std::vector<std::shared_ptr<Toy>> toys_;
    
    // 私有工具函数
    std::shared_ptr<Toy> findToyByName(const std::string& name) const;
    std::string typeToString(ToyType type) const;
};
ToyFactory.hpp
#include "ToyFactory.hpp"
#include <iostream>
#include <iomanip>

ToyFactory::ToyFactory() {
    createSampleToys();
}

std::shared_ptr<Toy> ToyFactory::createToy(ToyType type, const std::string& name, float price) {
    std::shared_ptr<Toy> toy;
    
    switch(type) {
        case ToyType::TEDDY_BEAR:
            toy = std::make_shared<TeddyBear>(name, price);
            break;
        case ToyType::ROBOT_DOG:
            toy = std::make_shared<RobotDog>(name, price);
            break;
        case ToyType::MUSIC_RABBIT:
            toy = std::make_shared<MusicRabbit>(name, price);
            break;
        case ToyType::TALKING_BIRD:
            toy = std::make_shared<TalkingBird>(name, price);
            break;
    }
    
    if (toy) {
        toys_.push_back(toy);
        std::cout << "成功创建玩具: " << name << std::endl;
    }
    
    return toy;
}

void ToyFactory::createSampleToys() {
    createToy(ToyType::TEDDY_BEAR, "温暖小熊", 199.99);
    createToy(ToyType::ROBOT_DOG, "智能机器狗", 599.99);
    createToy(ToyType::MUSIC_RABBIT, "音乐小兔", 299.99);
    createToy(ToyType::TALKING_BIRD, "学舌鹦鹉", 399.99);
    createToy(ToyType::TEDDY_BEAR, "棕色泰迪", 159.99);
}

void ToyFactory::showAllToys() const {
    std::cout << "\n========== 玩具工厂库存 ==========" << std::endl;
    std::cout << "玩具总数: " << toys_.size() << std::endl;
    std::cout << "----------------------------------" << std::endl;
    
    for (const auto& toy : toys_) {
        toy->showInfo();
    }
    
    std::cout << "==================================" << std::endl;
}

void ToyFactory::showToysByType(ToyType type) const {
    std::string type_name = typeToString(type);
    std::cout << "\n========== " << type_name << "类玩具 ==========" << std::endl;
    
    int count = 0;
    for (const auto& toy : toys_) {
        if (toy->getType() == type) {
            toy->showInfo();
            count++;
        }
    }
    
    std::cout << "共找到 " << count << "" << type_name << std::endl;
}

void ToyFactory::playWithToy(const std::string& name) {
    auto toy = findToyByName(name);
    if (toy) {
        std::cout << "\n开始玩 " << name << "" << std::endl;
        toy->play();
        
        // 根据具体类型调用特异功能
        if (auto teddy = std::dynamic_pointer_cast<TeddyBear>(toy)) {
            teddy->hug();
        } else if (auto dog = std::dynamic_pointer_cast<RobotDog>(toy)) {
            dog->fetch();
        } else if (auto rabbit = std::dynamic_pointer_cast<MusicRabbit>(toy)) {
            rabbit->dance();
        } else if (auto bird = std::dynamic_pointer_cast<TalkingBird>(toy)) {
            bird->repeat("这个玩具真好玩!");
        }
    } else {
        std::cout << "未找到玩具: " << name << std::endl;
    }
}

void ToyFactory::chargeAllToys() {
    std::cout << "\n正在为所有玩具充电..." << std::endl;
    for (const auto& toy : toys_) {
        toy->charge(30);
    }
}

int ToyFactory::getTotalToyCount() const {
    return toys_.size();
}

float ToyFactory::getTotalValue() const {
    float total = 0;
    for (const auto& toy : toys_) {
        total += toy->getPrice();
    }
    return total;
}

std::shared_ptr<Toy> ToyFactory::findToyByName(const std::string& name) const {
    for (const auto& toy : toys_) {
        if (toy->getName() == name) {
            return toy;
        }
    }
    return nullptr;
}

std::string ToyFactory::typeToString(ToyType type) const {
    switch(type) {
        case ToyType::TEDDY_BEAR: return "泰迪熊";
        case ToyType::ROBOT_DOG: return "机器狗";
        case ToyType::MUSIC_RABBIT: return "音乐兔";
        case ToyType::TALKING_BIRD: return "会说话的鸟";
        default: return "未知类型";
    }
}
ToyFactory.cpp
#include "ToyFactory.hpp"
#include <iostream>

void testToyFunctionality() {
    std::cout << "========== 测试玩具特异功能 ==========" << std::endl;
    
    // 创建单个玩具测试
    TeddyBear bear("测试小熊", 99.99);
    bear.showInfo();
    bear.play();
    bear.hug();
    bear.tellStory();
    
    std::cout << "\n";
    
    RobotDog dog("测试机器狗", 299.99);
    dog.showInfo();
    dog.play();
    dog.fetch();
    
    std::cout << "\n";
}

void testToyFactory() {
    std::cout << "\n========== 测试玩具工厂 ==========" << std::endl;
    
    ToyFactory factory;
    
    // 显示所有玩具
    factory.showAllToys();
    
    // 显示特定类型玩具
    factory.showToysByType(ToyType::TEDDY_BEAR);
    
    // 玩玩具
    std::cout << "\n";
    factory.playWithToy("温暖小熊");
    factory.playWithToy("智能机器狗");
    factory.playWithToy("音乐小兔");
    factory.playWithToy("学舌鹦鹉");
    
    // 充电测试
    std::cout << "\n";
    factory.chargeAllToys();
    
    // 添加新玩具
    std::cout << "\n";
    factory.createToy(ToyType::MUSIC_RABBIT, "粉色音乐兔", 349.99);
    
    // 显示更新后的库存
    std::cout << "\n";
    factory.showAllToys();
    
    // 显示统计信息
    std::cout << "\n========== 工厂统计信息 ==========" << std::endl;
    std::cout << "玩具总数: " << factory.getTotalToyCount() << std::endl;
    std::cout << "库存总价值: ¥" << factory.getTotalValue() << std::endl;
}

void testPolymorphism() {
    std::cout << "\n========== 测试多态性 ==========" << std::endl;
    
    // 创建不同类型的玩具,但使用基类指针
    std::shared_ptr<Toy> toys[] = {
        std::make_shared<TeddyBear>("多态小熊", 129.99),
        std::make_shared<RobotDog>("多态机器狗", 499.99),
        std::make_shared<MusicRabbit>("多态音乐兔", 279.99),
        std::make_shared<TalkingBird>("多态鹦鹉", 359.99)
    };
    
    // 统一接口调用不同的play方法
    for (const auto& toy : toys) {
        std::cout << "\n玩具: " << toy->getName() << std::endl;
        toy->play();  // 多态调用
    }
}

int main() {
    std::cout << "毛绒玩具管理系统测试" << std::endl;
    std::cout << "=======================" << std::endl;
    
    testToyFunctionality();
    testToyFactory();
    testPolymorphism();
    
    std::cout << "\n测试完成!" << std::endl;
    return 0;
}
demo4.cpp
#include "Toy.hpp"
#include <iostream>
#include <iomanip>
#include <algorithm>

// Toy基类实现
Toy::Toy(const std::string& name, ToyType type, float price)
    : name_(name), type_(type), price_(price),
      battery_level_(100), volume_level_(50), is_awake_(true) {}

void Toy::showInfo() const {
    std::cout << "玩具名称: " << name_ 
              << " | 类型: ";
    
    switch(type_) {
        case ToyType::TEDDY_BEAR: std::cout << "泰迪熊"; break;
        case ToyType::ROBOT_DOG: std::cout << "机器狗"; break;
        case ToyType::MUSIC_RABBIT: std::cout << "音乐兔"; break;
        case ToyType::TALKING_BIRD: std::cout << "会说话的鸟"; break;
    }
    
    std::cout << " | 价格: ¥" << std::fixed << std::setprecision(2) << price_
              << " | 电量: " << battery_level_ << "%"
              << " | 状态: " << (is_awake_ ? "唤醒" : "休眠") << std::endl;
}

void Toy::charge(int amount) {
    battery_level_ = std::min(100, battery_level_ + amount);
    std::cout << name_ << " 正在充电,当前电量: " << battery_level_ << "%" << std::endl;
}

void Toy::setVolume(int level) {
    volume_level_ = std::max(0, std::min(100, level));
    std::cout << name_ << " 音量设置为: " << volume_level_ << std::endl;
}

void Toy::sleep() {
    is_awake_ = false;
    std::cout << name_ << " 进入休眠模式" << std::endl;
}

void Toy::wakeUp() {
    is_awake_ = true;
    std::cout << name_ << " 已唤醒" << std::endl;
}

// TeddyBear实现
TeddyBear::TeddyBear(const std::string& name, float price)
    : Toy(name, ToyType::TEDDY_BEAR, price), hug_count_(0) {}

void TeddyBear::play() {
    if (battery_level_ <= 10) {
        std::cout << name_ << " 电量不足,请先充电!" << std::endl;
        return;
    }
    battery_level_ -= 5;
    std::cout << name_ << " 发出温暖的光芒并轻轻摇晃..." << std::endl;
}

void TeddyBear::hug() {
    hug_count_++;
    std::cout << name_ << " 感受到拥抱,心跳加速 ♥ (" 
              << hug_count_ << "次拥抱)" << std::endl;
}

void TeddyBear::tellStory() {
    std::cout << name_ << " 开始讲故事: \"从前在森林里有一只勇敢的小熊...\"" << std::endl;
}

// RobotDog实现
RobotDog::RobotDog(const std::string& name, float price)
    : Toy(name, ToyType::ROBOT_DOG, price), step_count_(0) {}

void RobotDog::play() {
    if (battery_level_ <= 15) {
        std::cout << name_ << " 电量不足,请先充电!" << std::endl;
        return;
    }
    battery_level_ -= 10;
    walk();
    bark();
}

void RobotDog::walk() {
    step_count_ += 10;
    std::cout << name_ << " 正在走路... 总步数: " << step_count_ << std::endl;
}

void RobotDog::bark() {
    std::cout << name_ << " 汪汪叫!" << std::endl;
}

void RobotDog::fetch() {
    std::cout << name_ << " 跑去捡球了!" << std::endl;
}

// MusicRabbit实现
MusicRabbit::MusicRabbit(const std::string& name, float price)
    : Toy(name, ToyType::MUSIC_RABBIT, price) {
    song_list_ = {"小星星", "欢乐颂", "摇篮曲", "生日快乐"};
}

void MusicRabbit::play() {
    if (battery_level_ <= 20) {
        std::cout << name_ << " 电量不足,请先充电!" << std::endl;
        return;
    }
    battery_level_ -= 8;
    playMusic(0);
    dance();
}

void MusicRabbit::playMusic(int song_id) {
    if (song_id >= 0 && song_id < song_list_.size()) {
        std::cout << name_ << " 播放音乐: " << song_list_[song_id] << std::endl;
    }
}

void MusicRabbit::dance() {
    std::cout << name_ << " 随着音乐摇摆跳舞!" << std::endl;
}

void MusicRabbit::recordMessage(const std::string& message) {
    recorded_message_ = message;
    std::cout << name_ << " 已录音: " << message << std::endl;
}

// TalkingBird实现
TalkingBird::TalkingBird(const std::string& name, float price)
    : Toy(name, ToyType::TALKING_BIRD, price) {
    learned_phrases_ = {"你好", "再见", "我爱你"};
}

void TalkingBird::play() {
    if (battery_level_ <= 25) {
        std::cout << name_ << " 电量不足,请先充电!" << std::endl;
        return;
    }
    battery_level_ -= 12;
    repeat("你今天过得怎么样?");
    sing();
    flyAnimation();
}

void TalkingBird::repeat(const std::string& phrase) {
    learned_phrases_.push_back(phrase);
    std::cout << name_ << " 说: " << phrase << std::endl;
}

void TalkingBird::sing() {
    std::cout << name_ << " 在唱歌: 叽叽喳喳~ 叽叽喳喳~" << std::endl;
}

void TalkingBird::flyAnimation() {
    std::cout << name_ << " 展开翅膀,做出飞翔的动作!" << std::endl;
}
Toy.cpp

image

 

image

 

 
posted @ 2025-12-02 20:32  崎膺  阅读(0)  评论(0)    收藏  举报