简体   繁体   中英

C++ Polymorphism- call derived class method with different signature

I am making an ecosystem simulation in C++. In it there are animals that can be herbivores or carnivores.

Carnivores only eat other herbivores, so when carnivores eat() , they must know the direction of the herbivore.

Herbivores only eat grass, so they need not know the direction of anything, they simply eat whats underneath 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);
};

The function definitions are as follows:

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

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

When using virtual , dynamic-binding is used, so the compiler resolves the function call at run-time. But how can I get around to write code like this:

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

without getting this error ?

Problem:

I am getting an error:

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

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

It is referring to the base class Eat() which takes no arguments

Your classes do not currently override the pure virtual method in the base class. Any virtual overrides should have the same signature as the base class declaration. An easy way to solve the problem is make all overloads have access to the direction, with a definition like the following:

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

This way the overloads that need the direction have it, and the ones that don't need it can ignore it. Also, no dynamic_cast s are necessary.

The problem is that you use the dynamic cast only to check the class. this_animal is still a pointer to ANIMAL and does hence have no Eat function.

To solve your issue, you have to use the dynamic cast until the end:

 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM