跳过正文

丙加·第11章·答案

·391 字·2 分钟·
  1. 魔法少女扩展包

    // 前面是include和基类
    // ...
    
    class InabaMeguru : public MahouShojo {
    private:
        std::string name;
        bool firstTransform = true;  // 更清晰的状态标记
    
    public:
        InabaMeguru() {
            transformationPhrase = "Ciallo~(∠・ω< )⌒★";
        }
    
        void transform() override {
            // 当然,name.empty() 效果是一样的
            // 但是这样语义更清晰
            if (firstTransform) {
                std::cout << "Senpai, o namae o oshiete itadakemasu ka?" << std::endl;
                std::getline(std::cin, name);
                firstTransform = false;
            }
            std::cout << name << ", " << transformationPhrase << std::endl;
        }
    };
    
    int main() {
        // 刻意使用了堆对象
        // 当然可以使用InabaMeguru mgr;这样的栈对象
        InabaMeguru* mgr = new InabaMeguru;
    
        mgr->transform();
        mgr->transform();
    
        // 堆对象记得释放
        delete mgr;
        return 0;
    }
    
  2. 胰脏物语

    #include <iostream>
    #include <vector>
    #include<string>
    using namespace std;
    
    class KyoubyouBunko{
    private:
        vector<string>pages;
    
    public:
    
        KyoubyouBunko():pages{
            "20XX/11/29\nI don't want to write dark things, but I must... First, I apologize to my family."
            "20XX/12/04\nI've decided not to hate my fate. That's why I named this 'Kyoubyou Bunko'."
            "20XX/10/12\nI started dating someone new. I don't want to tell him about my illness."
        }{}
    
        friend class Best_friend;
    };
    
    class Best_friend{
    public:
    
        void read(const KyoubyouBunko& diary){
            cout<<"=== Reading KyoubyouBunko ==="<<endl;
            for(int i = 0; i<diary.pages.size();i++){
                cout<<(i+1)<<" page:"<<diary.pages[i]<<endl;
            }
            cout<<"============================="<<endl;
        }
    
        void write(KyoubyouBunko& diary, const string& new_page){
            diary.pages.push_back(new_page);
            cout <<"Added new diary page"<<endl;
        }
    };
    
    int main(){
        KyoubyouBunko diary;
        Best_friend haruki;
    
        haruki.read(diary);
    
        haruki.write(diary,"Ordinary words could never capture what you mean to me. \nThe truth is, I want to devour your pancreas!");
    
        haruki.read(diary);
    
        return 0;
    }
    
  3. 重构 ManaEntity

    #include <cstring> // for strcpy
    
    class ManaEntity {
    public:
        // 普通构造函数
        ManaEntity(EntityType t, int h, int m, const string& name)
            : type(t), HP(h), MP(m), entityName(name) }}
    
    	// 其实可以不写这个编译器也会默认生成,但是写出来更清楚
        ManaEntity(const ManaEntity& other) = default;
    
        ManaEntity(ManaEntity&& other) = default;
    
        ~ManaEntity() = default;
    
    private:
        EntityType type;
        int HP;
        int MP;
        std::string entityName;
    };
    

    由此可见,“0 原则”可以少造轮子,减少代码,让程序简洁易读。这就是"0原则"的魅力——让编译器和大佬们写的标准库为我们处理复杂的资源管理问题!

  4. 魔法少女乐队

    // 类定义、include语句
    // 别忘了vector
    // ...
    
    int main() {
        vector <MahouShoujo*> mahoushoujo_band;  // 又看一集(不是)
        mahoushoujo_band.push_back(new UnluckyNene);
        mahoushoujo_band.push_back(new SmartNene);
        mahoushoujo_band.push_back(new InabaMeguru);
    
        // 指针引用:auto* 这样可少拷贝一次
        // 当然这里直接auto也没错
        for (auto* mahoushoujo : mahoushoujo_band) {
            mahoushoujo->battle();
        }
    
        for (auto* mahoushoujo : mahoushoujo_band) {
            delete mahoushoujo;
        }
    
        return 0;
    }
    

    当然,智能指针可以不用手动释放:

    // 使用智能指针,避免手动内存管理
    #include <memory>
    
    int main() {
        std::vector<std::unique_ptr<MahouShojo>> mahoushoujo_band;
        mahoushoujo_band.push_back(std::make_unique<UnluckyNene>());
        mahoushoujo_band.push_back(std::make_unique<SmartNene>());
        mahoushoujo_band.push_back(std::make_unique<InabaMeguru>());
    
        for (auto& mahoushoujo : mahoushoujo_band) {
            mahoushoujo->battle();
        }
        // 不需要手动delete,自动释放内存
        return 0;
    }
    

    可能的输出:

    NeNeNeNeNe!
    Assault Launched!
    MP: 100
    NeNeNeNeNe
    Assault Launched!
    Uhhh...So hot...
    Toy charging, currently: 10
    MP: 70
    Senpai, o namae o oshiete itadakemasu ka?
    [等待用户输入,比如输入: Hoshina Shuuji]
    Hoshina Shuuji, Ciallo~(∠・ω< )⌒★
    Assault Launched!
    MP: 100
    

    通过这个输出可以看到,即使是相同的 battle() 接口,每个类的行为也不同

    1. UnluckyNene:使用基类的默认行为
    2. SmartNene:重写了 onanii(),MP损失更少且有额外效果
    3. InabaMeguru:重写了 transform(),有交互式输入

    这完美展示了C++多态性的威力!

命令提示符@CommandPrompt-Wang
作者
命令提示符@CommandPrompt-Wang