我是一名用C ++开发生态系统的初学者。它的工作原理如下:
我的网格上有PLANTS
(此处未显示)和ANIMALS
。
如果某个内容是ANIMAL
,则可以是CARNIVORE
或HERBIVORE
。
我创建了这个层次结构:
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查看是否允许一只动物吃另一只动物。具体而言,如果Animal
为A
且B
为A
,则CARNIVORE
B
仅允许吃动物HERBIVORE
。< / p>
像我一样嵌套这些类是否允许我稍后在编程中检查对象的类型?我现在不想认为这是正确的,必须改变它。
或者,除了dynamic_cast
(布尔is_carnivore
?)之外还有更好的方法,我应该使用它吗?我的目标是最可读和最好的OOP练习
答案 0 :(得分:4)
您的嵌套类根本不代表您想要的内容。不要再考虑这个结构来解决你的问题。相反:
有几种方法可以看出动物*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;
}
请注意,我使用了一个简单的整数,但很可能是一种更复杂的方法(可能会引入大小作为动物可以吃另一种动物的另一个决定因素)。正如我的评论所暗示的那样,有一些小食肉动物绝不会吃大食草动物。