c++ - dynamic_cast performing correctly only sometimes -
the structure of problem such food abstract base class; plant, , animal directly inherit that. herbivore, carnivore, , omnivore inherit animal, while fruits , nuts , leaves inherit plant lemur, koala, , squirrel inherit herbivore
overall it's hot mess, it's necessary exercise. entire project available on github https://github.com/joekitch/oop_jk_assignment_4/blob/master/oop_jk_assignment_4/lemur.h the full class diagram in on github
but here relevant bits , bobs (at least, ones believe relevant) first food class, contains nothing
#pragma once #include <string> #include <list> using namespace std; class food { public: food(){ } virtual ~food(){ } }; next animal, contains virtuals of hunt() , eat() functions
#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; }; this herbivore, defines hunt() function, problems start (see comment within hunt() ). hunt takes in list of type food* declared globally within 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; (list<food*>::iterator = foodlist.begin(); != foodlist.end(); it++) { if (plant* temp = dynamic_cast<plant*>(*it)) { //this there problems start. above dynamic cast should make temp //non-null if thing i'm looking @ child of plant (that is, if thing //in food list fruit or nut or leaf). , indeed does...but //next dynamic cast (in eat() function of lemur) doesn't detect fruits.... plantcounter++; if ( eat(*it) ) fruitcounter++; //return true; } } cout << "there " << fruitcounter << " fruits , " << plantcounter << " plants in list." << endl; return false; }; }; and here fruit class. nothing particularly notable, i'm placing here in case helps solve problem
#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 base class ~fruit(){ } //destructor //inherits plant base class, makes leae nodes in class tree easy write , access }; now here's real troublemaker. lemur defines eat() function, , takes food* passed hunt(), called herbivore, , more tests on see if it's fruit (which plant lemur can eat)
#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, sees every plant fruit in //case...at least according typeinfo().name() have run in here. temp //always returns null, proper if statement never happens, never sees //any fruit, though there's whole bunch in list (500 of them). what's wrong? cout << "it's fruit" << endl; return true; } else { //cout << "not fruit" << endl; return false; } } void printself() { cout << "i " << age << " year old, " << weight << " kilogram " << name << " " << calories << " calories." << endl; }; string& getname(){ return name; }; std::string name; bool alive; int age, calories, maxcalories; double weight; }; as can see, dynamic_cast never returns non null temp, though have confirmed traverses list. use counter variables track progress , strange thing says there 1500 plants in list...but 0 fruits...
am structuring casts wrong? inheritance off? do?
edit; added virtual destructors every class, isn't problem
from looking @ github repo, looks problem in main.cpp add object food_list:
else if (filein_type == plant_type) { plants++; filein >> filein_name >> filein_calories; food_list.push_back(new plant (filein_name, filein_calories) ); } you ever create plant object add list. that's dynamic type of objects be.
just above bit of code in main.cpp, have cascade of if/else statements create different animal types baed on animal name string. need similar plants.
Comments
Post a Comment