2016-04-12 16 views
2

私はC++でエコシステムを開発している初心者です。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 

私の問題:その後ラインダウン

を、私は1匹の動物が他の動物を食べることを許可されているかどうかを確認するためにdynamic_castを使用したいです。具体的には、AnimalAは、ACARNIVOREであり、Bであり、HERBIVOREである場合にのみ、動物Bを食べることが許される。

私はプログラミングの後半でオブジェクトのタイプをチェックできるようにクラスをネストしますか?私はこれが今正しいと思うことは望まないでしょうし、それをラインの下で変えなければなりません。

dynamic_cast(ブール値is_carnivore?)以外の方法が良い場合は、代わりにそれを使用する必要がありますか?私は最も読みやすく、最高のOOPの練習を目指しています

+1

なぜクラスをネストしたいのですか?なぜ、他のレベルの継承だけではないのですか? (そして、大文字でクラス名を書かないでください...) – Chiel

+0

ANIMALには仮想デストラクタが必要です。 –

+0

これは私のジレンマです。だから私はネストが間違ったアプローチだと仮定していますか?別のレベルの継承をどのように使用しますか? (okay) – user3487243

答えて

4

ネストされたクラスは、あなたが望むものをまったく表していません。あなたの問題に対処するためにこの構成をさらに検討しないでください。代わりに:

  • WOLFとCHEETAHは動物*aは動物*b他を食べることができるかどうかを確認するには、いくつかの方法が、その後がある草食動物

から継承shoulr CARNIVOREから

  • SQUIRRELとRABBITを継承する必要があります。最も簡単なアプローチは、あなたが提案したようにdynamic_castです:

    ANIMAL *a, *b; 
    ... 
    if (dynamic_cast<CARNIVORE*>(a) && dynamic_cast<HERBIVORE*>(b)) { 
        // *a can eat *b 
    } 
    

    しかし、これは最高のOOPプラクティスではありません。私はすべてのあなたの制約と要件を知っているわけではありませんが、あなたが最先端であり、より複雑なルール(主役の強さと健康、いくつかの種の例外など)をエンコードできるようにしたいならば。)あなたはdouble dispatchのいくつかの種類を実装するに興味がある可能性があり(here

  • +0

    @ user3487243はい、これは私がクラス構造のために意味したものです。 – Christophe

    +0

    元の回答であったコードを修正し始めると、ちょっと混乱します。新しい読者がこの質問に従うことは不可能になります。あなたの質問にあなたが参照する入れ子は、もはや見ることができません。 – Chiel

    +1

    ありがとう@キール、私は元に戻った。クリストフに尋ねなければならないことは、私が正しい道を歩いていたかどうかわかりませんでした。 – user3487243

    3

    もし正しいならば、各動物を生態系で独自のレベルにするという単純なことができます。このようなもの:

    class Animal { 
    Animal(int curr, int max, int rate, int level)... 
    
    } 
    

    その後、動物は低レベルの別の動物だけを食べるようにします。

    ような何か:thatsの場合は巣について

    if(animalA.level < animalB.level){ 
        ... 
    }else{ 
        ... 
    } 
    

    しかしでも法的かなりよくわからないイム。そのようなことをやろうとしたことはありません。

    +0

    私の肉食動物はそれぞれ草ではありませんが、私は別の条件付きでそれを回避することができます。ありがとう、これは動作します! – user3487243

    +0

    注:私の意見では、2番目の例の値チェックを行うための適切なアプローチは、値 –

    +0

    'Animal(int curr、int max、int rate、int level、bool isPlant)の戻り関数を作成することです。 '植物/動物の問題を解決することができました:)助けてうれしい! –

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

    あなたが相続の二つのレベルの私の提案の実行されている例を見つける(これ私はその間に回答としてeeが掲載されました)。

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

    Live Example

    注(多分他の動物を動物食べることができるために別の決定要因としてのサイズを導入します)。私のコメントが示唆しているように、大きな肉食動物を食べることは決してない小さな肉食動物があります。