C
Calum Grant
grahamo said:This came up in an interview I did a while ago and I wanted to know
the correct answer. The setup is this;
If I have a base class "food" and also two classes "meat" and "veg"
that inherit from food, thus;
food
/ \
/ \
meat veg
Also I have a base class human, and all humans eat so there's a method
eat defined thus (* denotes the method eat)
human *----void (eat& food)
/ \
/ \
vegetarian carnivore
Now the question is how do we work things such that a vegaterian will
never eat meat, in terms of our class design etc. There's probably a
million and one answers but I'd like to get the best one from the
experts on this group
At first sight, inheritance might seem a suitable tool for this problem.
struct Carnivore
{
virtual void eat(Meat&)=0;
};
struct Herbivore
{
virtual void eat(Herbs&)=0;
};
struct Omnivore : public Carnivore, public Herbivore
{
};
Great! Omnivores eat both types of food.
But, what if we had a composite food containing both Meat and Herbs?
struct Pie : public Meat, public Herbs
{
};
An omnivore could eat a pie (but it would have to be cast as Meat or
Herbs), but you can feed a Pie to a Herbivore, which is perhaps not the
intended behaviour.
One could have quite complicated rules about what can eat what, and one
needs to be able to deal with exceptions (e.g. I am an omnivore, but I
don't eat tomatoes, nuts or monkey). I don't think inheritance can
represent such rules.
So you might need to take a step back and just write
struct Eater
{
virtual void eat(Food&)=0;
};
and derive class hierarchies from Eater and Food. Eater will check the
food using dynamic_casts, and throw exceptions (or perform other
actions) depending on the food type. It's not so pretty but it is
flexible and will work.