dimanche 5 septembre 2021

C++ Inheritance: arguments of derived class type in virtual function with base class types

I'm having a rough time with a particular C++ inheritance problem. Apologies if it got answered before, but I just couldn't find a proper answer. Say we have two abstract classes, one using the other as argument type for one of the pure virtual functions:

class Food {
  public:
    int calories=0;
    virtual void set_calories(int cal)=0;
}

class Animal {
  public:
   int eaten_calories=0;
   virtual void eat_food(Food &f)=0;
}

Now, we create a derived class for each, and we instantiate a virtual function with arguments of type the derived class:

class Vegetables: public Food{
  public:
   void set_calories(int cal){calories=cal;}
}
class Cow: public Animal{
  public:
   void eat_food(Vegetables &v){this->eaten_calories += v.calories;}
}

The problem with this is that the function eat_food requires a signature with the abstract class Food, or else a Cow() object creation won't compile, complaining that Cow is an abstract class because no suitable implementation of eat_food(Food f) was found.

Update: An additional constraint I seek for the implementation is that a second class Meat: public Food should not be usable with Cow::eat_food(f). In short, just setting Cow::eat_food(Food f) and casting to Vegetables wouldn't cut it.

What is the best way to overcome this error?

So far I have found two options:

  1. Creating an eat_food(Food f) implementation in Cow with a try/catch to check if f can be safely casted to Vegetables, and then calling eat_food(Vegetables v). PROBLEM: if you have 50 virtual functions, this forces you to write 50 additional function implementations in Cow.
  2. Turn the Animal into a Template class Animal<T>, and instantiate it with each of the derived classes of Food to define the animals (e.g., class Cow: public Animal<Vegetables>). *PROBLEM: you can no longer define an Animal* pointer to hold an undefined animal with not known type.

Is there any viable/stylish alternative to these two? Maybe a software pattern of some kind?

Aucun commentaire:

Enregistrer un commentaire