dynamic_cast работает правильно только иногда

структура проблемы такая
Еда — это абстрактный базовый класс; Растение и животное напрямую наследуют это.
Травоядные, плотоядные и всеядные наследуются от животных,
в то время как фрукты и орехи и листья наследуются от растений
Лемур, коала и белка наследуются от травоядных

В целом это горячий беспорядок, но это необходимо для упражнения.
весь проект доступен на GitHub
https://github.com/joekitch/OOP_JK_Assignment_4/blob/master/OOP_JK_Assignment_4/Lemur.h
полная диаграмма классов находится также на GitHub

но вот соответствующие биты и бобы (по крайней мере, те, которые я считаю актуальными)
Сначала класс еды, который почти ничего не содержит

#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 ()). Охота принимает список типа 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 () и получает Food *, который был передан ему от 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 никогда не возвращает ненулевое значение temp, хотя я подтвердил, что он пересекает список. я также использую переменные счетчика для отслеживания его прогресса, и странно то, что он говорит, что в списке 1500 растений … но 0 фруктов …

я правильно структурирую свои броски? мое наследство выключено? что?

редактировать; я добавил виртуальные деструкторы для каждого класса, так что это не проблема

0

Решение

глядя на репозиторий GitHub, похоже, что проблема в 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 операторы, которые создают различные типы животных на основе имени животного. Вам нужно сделать что-то подобное для растений.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector