2016-04-16 7 views
1

私はC++でエコシステムシミュレーションを行っています。その中には、草食動物や肉食動物になる動物があります。C++異なる署名を持つ多態性呼び出し派生クラスメソッド

肉食動物は他の草食動物しか食べないので、肉食動物eat()を食べるときは、彼らは草食動物の方向を知る必要があります。

void HERBIVORE::Eat(CELL field[40][30], int x, int y) 
{ 
} 

void CARNIVORE::Eat(CELL field[40][30], int x, int y, char direction) 
{ 
} 

を使用する場合:them.as

class ANIMAL 
{ 
public: 
ANIMAL(...) 
: ... 
{ 
} 
virtual ~ANIMAL() 
{} 

//does nothing, just stating that every animal must implement an Eat() method 
virtual void Eat() = 0; 
}; 

class HERBIVORE : public ANIMAL 
{ 
public: 
HERBIVORE(...) 
: ANIMAL(...) 
{} 
void Eat(CELL field[40][30], int x, int y); 
}; 


class CARNIVORE : public ANIMAL 
{ 
public: 
CARNIVORE(...) 
: ANIMAL(...) 
{} 

void Eat(CELL field[40][30], int x, int y, char direction); 
}; 

関数定義の下にあるいただきました、以下のように、彼らは単に食べ、

草食動物は草を食べるので、彼らは何の方向性を知っている必要はありませんvirtual、dynamic-bindingが使用されるため、コンパイラは実行時に関数呼び出しを解決します。しかし、どうすればこのようなコードを書くことができます:

if (dynamic_cast<CARNIVORE*>(this_animal)) //if carnivore 
    this_animal->Eat(field, i, j, direction); 

    if (dynamic_cast<HERBIVORE*>(this_animal)) //if herbivore 
    this_animal->Eat(field, i, j); 

このエラーは発生しませんか?

問題:

私はエラーを取得しています:

'ANIMAL::Eat': function does not take 3 arguments

'ANIMAL::Eat': function does not take 4 arguments

それは食べる基底クラスを参照している()

+4

このライン '場合((this_animalはdynamic_cast))'、あなたのデザインを再考するべきものです。私の2セント。 – skypjack

+1

私は、仮想関数は同じ署名を持っている必要があります - 私はドキュメントをチェックします。 – tomascapek

+1

仮想関数をオーバーライドする場合は、同じシグネチャを指定する必要があります – DarthRubik

答えて

1

問題は、クラスをチェックするためにのみ動的キャストを使用することです。 this_animalはまだANIMALへのポインタなので、Eat関数はありません。

はあなたの問題を解決するために、あなたは最後まで動的キャストを使用する必要があります。

if (dynamic_cast<CARNIVORE*>(this_animal)) //if carnivore 
    dynamic_cast<CARNIVORE*>(this_animal)->Eat(field, i, j, direction); // 4 args 

if (dynamic_cast<HERBIVORE*>(this_animal)) //if herbivore 
    dynamic_cast<CARNIVORE*>(this_animal)->Eat(field, i, j); // 3 args 
+0

これは私が探していたものです。私は第2のダイナミックキャストを逃していた。ありがとうございました – user3487243

2

あなたのクラスは現在オーバーライドしない引数を取りません基本クラスの純粋仮想メソッド。すべての仮想オーバーライドは、基本クラス宣言と同じシグネチャを持つ必要があります。

void Eat(CELL field[40][30], int x, int y, char direction) 
{ 
    ... 
} 

方向を必要とする過負荷がそれを持っている。この方法で、かつ必要としないもの:問題を解決する簡単な方法は、以下のように定義して、すべてのオーバーロードが方向へのアクセス権を持って作るですそれを無視することができます。また、dynamic_castは必要ありません。

+0

この回答は仮想多型に近づく方法です。可能であればdynamic_cast(特にそれらの2つ)を避け、均一なインターフェースを設定してください(おそらく "ここ"の方向を使用する)、dynamic_castを使用してクラスの特性呼び出しコードが利用可能な各派生クラスを認識する必要があります。代わりに、クラスに特性をチェックする方法を与えます。EatsAnimals()とEatsGrass()を呼び出すのと同じように、ある日OMNIVOREを追加すると、 "多型"をまったく使用していなかった場合と同じように、アプリケーションのコードをすべてリファクタリングする必要はありません。 –