C ++生态系统模拟器(继承)

时间:2016-04-12 21:05:08

标签: c++ inheritance instance

我是一名用C ++开发生态系统的初学者。它的工作原理如下:

我的网格上有PLANTS(此处未显示)和ANIMALS

如果某个内容是ANIMAL,则可以是CARNIVOREHERBIVORE

我创建了这个层次结构:

class ANIMAL
{
private:
    int a_CUR_food_lvl; 
    const int a_MAX_food_lvl; 
    const int a_hunger_rate; 

public:

    ANIMAL(int curr, int max, int rate)
        : a_CUR_food_lvl(curr),
        a_MAX_food_lvl(max),
        a_hunger_rate(rate)
    {}

     virtual ~ANIMAL()
     {
        delete this;
     }

    virtual void Move() = 0;
    virtual void Eat() = 0;
    virtual void Evade() = 0;
    virtual void Reproduce() = 0;
    virtual void Die() = 0;
    virtual void Age() = 0;

    virtual int get_a_CUR_food_lvl() { return a_CUR_food_lvl; };
    virtual int get_a_MAX_food_lvl() { return a_MAX_food_lvl; };
    virtual int get_a_hunger_rate() { return a_hunger_rate; };
}; //end ANIMAL class


//#################################################################
class CARNIVORE : public ANIMAL
{
public:

    class WOLF : public ANIMAL
    {
        WOLF()
            : ANIMAL(150, 200, 2)
        {}
    };

    class CHEETAH : public ANIMAL
    {
        CHEETAH()
            : ANIMAL(75, 125, 5)
        {}
    };
}; //end CARNIVORE class


//#################################################################
class HERBIVORE : public ANIMAL
{
public:


    class RABBIT : public ANIMAL
    {
        RABBIT()
            : ANIMAL(150, 200, 2)
        {}
    };


    class SQUIRREL : public ANIMAL
    {
        SQUIRREL()
            : ANIMAL(150, 200, 2)
        {}
    };
}; //end HERBIVORE class

我的问题:

稍后,我想用dynamic_cast查看是否允许一只动物吃另一只动物。具体而言,如果AnimalABA,则CARNIVORE B仅允许吃动物HERBIVORE。< / p>

像我一样嵌套这些类是否允许我稍后在编程中检查对象的类型?我现在不想认为这是正确的,必须改变它。

或者,除了dynamic_cast(布尔is_carnivore?)之外还有更好的方法,我应该使用它吗?我的目标是最可读和最好的OOP练习

5 个答案:

答案 0 :(得分:4)

您的嵌套类根本不代表您想要的内容。不要再考虑这个结构来解决你的问题。相反:

  • WOLF和CHEETAH应该继承自CARNIVORE
  • SQUIRREL和RABBIT肩从HERBIVORE继承

有几种方法可以看出动物*a是否可以吃动物*b。正如您所建议的那样,最简单的方法是dynamic_cast:

ANIMAL *a, *b; 
...
if (dynamic_cast<CARNIVORE*>(a) && dynamic_cast<HERBIVORE*>(b)) {
     // *a can eat *b
}

但这不是最好的OOP练习。我不知道你所有的约束和要求,但如果你想成为最先进的技术并且能够编码更复杂的规则(如主角的力量和健康,某些物种的例外等等)你可能有兴趣实现某种double dispatch(例如讨论here

答案 1 :(得分:3)

如果我是正确的,你可以做一些简单的事情,就像让每只动物在生态系统中拥有自己的水平一样。像这样:

class Animal {
Animal(int curr, int max, int rate, int level)...

}

然后再这样做,动物只能吃另一种较低水平的动物。

类似的东西:

if(animalA.level < animalB.level){
    ...
}else{
    ...
}

关于巢但是我很不确定这是否合法。从来没有试过这样做,我可能不会。

答案 2 :(得分:1)

您已经有了部分答案,virtual功能就是您所需要的。您将在基类中定义名为isCarnivore()isHerbivore()的虚函数,然后在派生类中创建定义,以根据对象的类型返回true或false。

示例:

class ANIMAL {
public:
    virtual bool isHerbivore() = 0; //overload this in your derived class to determine if it is a carnivore
    bool isCarnivore() {
        return !isHerbivore(); // if its an herbivore it cannot be a carnivore and vice versa
    }
};

class CARNIVORE : public ANIMAL {
    virtual bool isHerbivore() override {
        return false;
    }
};

class HERBIVORE : public ANIMAL {
    virtual bool isHerbivore() override {
        return true;
    }
};

答案 3 :(得分:1)

在这里,您可以找到我的两个继承级别建议的运行示例(我看到它已经在此期间作为答案发布):

#include <iostream>

struct Animal
{
    virtual ~Animal() {};
};
struct Carnivore : public Animal {};
struct Herbivore : public Animal {};
struct Wolf      : public Carnivore {};
struct Cheetah   : public Carnivore {};
struct Squirrel  : public Herbivore {};
struct Rabbit    : public Herbivore {};

bool can_eat(Animal* predator, Animal* prey)
{
    return ( dynamic_cast<Carnivore*>(predator) && dynamic_cast<Herbivore*>(prey) );
}

int main()
{
    Animal* wolf   = new Wolf();
    Animal* rabbit = new Rabbit();

    std::cout << "Wolf eats rabbit = " << can_eat(wolf, rabbit) << std::endl;
    std::cout << "Rabbit eats wolf = " << can_eat(rabbit, wolf) << std::endl;

    return 0;
}

答案 4 :(得分:1)

您可以简单地将一个属性添加到表示食物链层次结构的基类。例如:

#include <iostream>
class Animal
{
    private:
        int a_CUR_food_lvl; 
        int food_chain_level;
        const int a_MAX_food_lvl; 
        const int a_hunger_rate; 

   public:
        Animal(int curr, int max, int rate, int food_chain)
        : a_CUR_food_lvl(curr), a_MAX_food_lvl(max),
        a_hunger_rate(rate), food_chain_level(food_chain) {}

        bool canEat(Animal& theAnimal) const
        { return food_chain_level > theAnimal.food_chain_level; } 
//...
}; 

class Carnivore : public Animal
{
   public:
        Carnivore(int curr, int max, int rate) : Animal(curr, max, rate, 2) {}
};

class Herbivore : public Animal
{
   public:
        Herbivore(int curr, int max, int rate) : Animal(curr, max, rate, 1) {}
};

class Insect : public Animal
{
   public:
        Insect(int curr, int max, int rate) : Animal(curr, max, rate, 0) {}
};

Carnivore Wolf(150, 200, 2);
Carnivore Cheetah(75,125,2);
Herbivore Squirrel(150,200,2);

using namespace std;

int main()
{
   cout << (Wolf.canEat(Squirrel)?"true":"false") << endl;
   cout << (Squirrel.canEat(Cheetah)?"true":"false") << endl;
}

Live Example

请注意,我使用了一个简单的整数,但很可能是一种更复杂的方法(可能会引入大小作为动物可以吃另一种动物的另一个决定因素)。正如我的评论所暗示的那样,有一些小食肉动物绝不会吃大食草动物。