问题的结构就是这样 食物是一个抽象的基类;植物和动物直接从中继承。 Herbivore,Carnivore和Omnivore继承自Animal, 而水果,坚果和叶子则来自植物 Lemur,Koala和Squirrel继承自Herbivore
总的来说,这是一个热点,但这是锻炼的必要条件。 整个项目可在GitHub上获得 https://github.com/joekitch/OOP_JK_Assignment_4/blob/master/OOP_JK_Assignment_4/Lemur.h 完整的类图也在GitHub上但这里是相关的位和bobs(至少,我认为是相关的) 首先是食品类,几乎没有任何东西
#pragma once
#include <string>
#include <list>
using namespace std;
class Food
{
public:
Food(){ }
virtual ~Food(){ }
};
接下来是Animal,其中包含hunt()和eat()函数的虚拟内容
#pragma once
#include "Food.h"
#include "Animal.h"
#include "Plant.h"
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Animal : public Food
{
public:
Animal(void) : name(), alive(true), age(0), calories(0), weight(0) { }
Animal(string& animal_name, int animal_age, int animal_calories, double animal_weight) :
name(animal_name), alive(true), age(animal_age), calories(animal_calories), weight(animal_weight), maxcalories(animal_calories) {}
virtual ~Animal(){}
virtual bool eat(Food* food){return false;};
virtual bool hunt(list<Food*> &foodlist){return false;};
virtual void PrintSelf(){};
virtual string& getName(){
return name;
};
std::string name;
bool alive;
int age, calories, maxcalories;
double weight;
};
这是Herbivore,它完全定义了hunt()函数,这就是问题的起点(参见我在hunt()中的评论)。 hunt接收一个类型为Food *的列表,该列表在main()
中全局声明#pragma once
#include "Animal.h"
//#include "Lemur.h"
#include "Plant.h"
#include "Fruit.h"
#include "Leaf.h"
#include "Nut.h"
#include <iostream>
#include <string>
#include <list>
#include <typeinfo>
using namespace std;
class Herbivore : public virtual Animal
{
public:
Herbivore() {}
virtual ~Herbivore(){}
virtual bool eat(Food* food) {cout << "herbivore.h eat() called" << endl; return true;};
bool hunt(list<Food*> &foodlist) //herbivore version of hunt()
{
int fruitcounter=0;
int plantcounter=0;
string name;
for (list<Food*>::iterator it = foodlist.begin(); it != foodlist.end(); it++)
{
if (Plant* temp = dynamic_cast<Plant*>(*it))
{
//this is there the problems start. the above dynamic cast SHOULD make temp
//non-null if the thing i'm looking at is a child of plant (that is, if the thing
//in the food list is a fruit or a nut or a leaf). And indeed it does...but the
//next dynamic cast (in the eat() function of Lemur) doesn't detect any fruits....
plantcounter++;
if ( eat(*it) )
fruitcounter++;
//return true;
}
}
cout << "there are " << fruitcounter << " fruits and " << plantcounter << " plants in the list." << endl;
return false;
};
};
这是Fruit类。没有什么特别值得注意的,我只是把它放在这里以防它们有助于解决问题
#pragma once
#include <iostream>
#include <string>
#include "Plant.h"
using namespace std;
class Fruit : public Plant {
public:
Fruit (std::string& plant_name, int energy_value):
Plant (plant_name, energy_value){} //constructor pased to base class
~Fruit(){ } //destructor
//inherits basically everything from the Plant base class, makes leae nodes in the class tree easy to write and access
};
现在这里是真正的麻烦制造者。这个狐猴完全定义了eat()函数,并从食草动物中调用它从hunt()传递给它的食物*,并对它做了更多的测试,看看它是否是一种水果(这是唯一的狐猴植物)可以吃)
#pragma once
#include "Animal.h"
#include "Herbivore.h"
#include "Plant.h"
#include "Fruit.h"
#include "Leaf.h"
#include "Nut.h"
#include <iostream>
#include <string>
#include <list>
#include <typeinfo>
using namespace std;
class Lemur : public Herbivore
{
public:
Lemur(void) : name(), alive(true), age(0), calories(0), weight(0) {}
Lemur(string& animal_name, int animal_age, int animal_calories, double animal_weight) :
name(animal_name), alive(true), age(animal_age), calories(animal_calories), weight(animal_weight), maxcalories(animal_calories) {}
~Lemur(){}
bool eat(Food* food)
{
if (Fruit* temp = dynamic_cast<Fruit*>(food))
{
//PROBLEM, it sees every plant as a fruit in this
//case...at least according to a typeinfo().name() that i have run in here. However the temp
//always returns null, so this proper if statement never actually happens, so it never sees
//any fruit, even though there's a whole bunch in the list (500 of them). what's wrong?
cout << "it's a fruit" << endl;
return true;
}
else
{
//cout << "not a fruit" << endl;
return false;
}
}
void PrintSelf()
{
cout << "i am a " << age << " year old, " << weight << " kilogram " << name << " with " << calories << " calories." << endl;
};
string& getName(){
return name;
};
std::string name;
bool alive;
int age, calories, maxcalories;
double weight;
};
正如您所看到的,dynamic_cast永远不会返回非null temp,即使我已经确认它遍历列表。我也使用计数器变量来跟踪它的进展,奇怪的是它说列表中有1500种植物......但是0种果实......
我构建错误的演员吗?是我的遗产吗?怎么办?
编辑;我为每个类添加了虚拟析构函数,所以这不是问题
答案 0 :(得分:0)
从查看github repo看,问题出现在main.cpp
中,您将对象添加到Food_list
:
else if (FileIn_type == Plant_type)
{
Plants++;
FileIn >> FileIn_name >> FileIn_calories;
Food_list.push_back(new Plant (FileIn_name, FileIn_calories) );
}
您只需创建一个Plant
对象即可添加到列表中。这就是所有这些对象的动态类型。
在main.cpp
的代码之上,您有一系列if/else
语句,可以在动物名称字符串上创建不同的动物类型。你需要为植物做类似的事情。