0

問題の構造は次のとおりです。Food は抽象基底クラスです。Plant と Animal はそれを直接継承します。草食動物、肉食動物、雑食動物は動物から継承し、果実、木の実、葉は植物から継承します。キツネザル、コアラ、リスは草食動物から継承します。

全体的にはめちゃくちゃですが、運動には必要です。プロジェクト全体は 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;
};

これは草食動物で、hunt() 関数を完全に定義しています。ここから問題が始まります (hunt() 内の私のコメントを参照してください)。ハントは、main() 内でグローバルに宣言されたタイプ Food* のリストを受け取ります

#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;
        };


};

ここにフルーツクラスがあります。特に注目すべきことはありません。問題の解決に役立つ場合に備えて、ここに配置しています

#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() から渡された Food* を受け取り、それが果物であるかどうかをさらにテストします (これはキツネザルの唯一の植物です)。食べることができます)

#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 以外の一時値を返すことはありません。また、カウンター変数を使用してその進行状況を追跡しますが、奇妙なことに、リストには1500個の植物があると言われています...しかし、果物は0です...

キャストの構造が間違っていますか? 私の継承はオフですか?どうする?

編集; すべてのクラスに仮想デストラクタを追加したので、それは問題ではありません

4

1 に答える 1

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植物についても同様のことを行う必要があります。

于 2013-05-10T07:58:49.030 に答える