实现多态的想法

时间:2016-12-13 19:51:12

标签: c++ polymorphism abstract

我正在开发c ++ roguelike RPG游戏。现在我正在进行任务系统,其想法是有抽象类Quest,每个新任务(例如"杀死守卫")是新类,每个任务包含一些目标我们需要做的抽象Objective类,一个接一个。那个工作正常。问题是目标彼此不同,例如

class KillMonstersWhole : public Objective
{
    vector<KillMonster> vector_of_monsters_to_kill;
public:
    virtual void ShowObjectiveStatus();
    virtual void CheckIfConditionsFilled();
    virtual vector<KillMonster> GetMonstersToKill() { return vector_of_monsters_to_kill; }
    virtual vector<KillMonster>::iterator GetBeginOfMonstersToKill() { return vector_of_monsters_to_kill.begin(); }
    virtual vector<KillMonster>::iterator GetEndOfMonstersToKill() { return vector_of_monsters_to_kill.end(); }
    KillMonstersWhole(int amount, KillMonster first, ...);
};

该类需要一些指定的函数,如GetMonsterToKill()等(从抽象的Objective继承),但是,例如

    class ReachXY : public Objective
{
    int x, y;
    string status_text;
public:     
    virtual void ShowObjectiveStatus();
    virtual void CheckIfConditionsFilled();
    ReachXY(int x, int y, string status_text);
};

不需要它,我也不知道如何在不创建任何不做任何事情的空白功能的情况下实现它的方法,这将会破坏我的代码。我想保留一个抽象类的继承,因为它工作得很好 - 在类Quest中我只有一个Objective *对象的向量。我知道我可以,例如在基础Objective类中创建vector_of_monsters_to_kill,然后在其中创建一个非纯的虚函数,但ReachXY会占用额外的,不可用的地方。当我将这些函数设置为非虚拟并将它们放入KillMonstersWhole类时,我将无法通过多态指针Objective *获得该函数。有任何聪明的方法吗? Objective和Quest类使一切变得清晰:

class Objective
{
protected:
    bool conditions_fullfilled;
    OBJECTIVE_ID id;
public:
    Objective() {}
    bool GetConditionsState() { return conditions_fullfilled; }
    virtual void ShowObjectiveStatus() = 0;
    virtual void CheckIfConditionsFilled() = 0;
    virtual vector<KillMonster> GetMonstersToKill() = 0;
    virtual vector<KillMonster>::iterator GetBeginOfMonstersToKill() = 0;
    virtual vector<KillMonster>::iterator GetEndOfMonstersToKill() = 0;
    virtual OBJECTIVE_ID GetID() { return id; }
    virtual ~Objective() {}
};

class Quest
{
protected:
    string name;
    vector<Objective*> objectives_list;
    vector<Objective*>::iterator quest_state;
public:
    Quest() {}
    vector<Objective*>::iterator GetQuestState() { return quest_state; }
    OBJECTIVE_ID GetQuestStateID();
    vector<Objective*> GetObjectivesList() { return objectives_list; }
    virtual void CheckRaiseQuestState();
    virtual void ShowDescription() = 0;
    virtual ~Quest() {}
};

1 个答案:

答案 0 :(得分:1)

让更高级别的类保持愚蠢,并使用较低级别的类来完成详细的工作。如果另一个类需要知道任务的状态,那么应该有一个非常通用的接口,比如

std::string Objective::getStatus() 

对于经典的Rat-Killing任务,将实施类似

的任务
std::string RatKiller::getStatus() 
{
    switch (ratcounter)        
    {
        case 0:
            return "Rodents Of Unusual Size? I KNOW they don't exist. Heh heh heh."
        case 1:
            return "You need to kill 1 more rat!"
        default:
            return "You need to kill " + std::to_string(ratcounter) + " more rats!"
    }
}

如果英雄的目标是收集一个波旁威士忌,一个苏格兰威士忌和一个啤酒,getStatus查看英雄的库存,找到波本威士忌和苏格兰威士忌并返回&#34; Thorogood毁灭者仍然需要一杯啤酒!&#34;

这样,顶层不会给出目标是什么样的smurf,它只显示一个字符串。

我在这里使用了一个字符串,因为它没有比字符串更通用,但你可以使用一个对所有人都通用的状态结构。

struct status
{
    std::string message;
    double percentComplete;
    std::vector<std::string> othernotes; 
    // more general information here
};

如果英雄执行动作(例如杀死怪物),将该信息传递到目标中,目标将相应地更新其内部状态。

void RatKiller::updateStatus(Action & actionPerformed)
{
    if (actionPerformed.getActionType() == KilledRat)
    {
        if (ratcounter > 0) 
        {
            ratcounter--;
        }
    }
}