class Animal
{
};
class Herbivore:Animal
{
void eat();
};
class Carnivore:Animal
{
void eat();
};
class Food
{
bool bMeat;
bool bVegeable;
};
I start out this class and all of a sudden I don't know what to do to with the class Food, as I would like to print out the correct food type each "kind" of animal favors most.
Sorry my food class size is small but I can't delete it as my whole program requires it to distinguish the food type. I will not mind if you suggest a different solution.
Since this is homework, I'm not going to post a code snippet, I'll just try to explain (and by trees, I assume you mean inheritance).
I see that you've fixed the animals not inheriting from Animal which is good. However, to incorporate Food into the mix, you probably want to have a member of Animal (so every subclass of Animal has to have it) that is a Food called favouriteFood or something similar, which is initialized in the constructor of each subclass of Animal to that animal's favourite food.
The second thing I think you'll want to do is to make the member function eat both virtual and part of Animal so that each subclass of Animal has that member (and virtual so that when you call the function through an Animal* or &, it will call the correct version). Then make eat have one parameter which is a Food, the food they are eating.
Try something like bool eat(Food & food). In eat you can then check if your animal likes it and either return false or consume the food and return true. It might also make sense to throw a bad_food exception instead of the return value.
Here's what I would try:
class Food;
class Vegetable : Food { ; };
class Meat : Food { ; }
struct Animal
{
virtual void eat(const Food& f)
{;} // Stubbed.
};
struct Herbivore : Animal
{
virtual void eat(const Vegetable&) = 0;
};
struct Carnivore : Animal
{
virtual void eat(const Meat&) = 0;
};
struct Omnivore : Animal
{
void eat(const Food& f)
{ cout << "I'm not picky.\n"; }
};
I suggest you look up concepts such as double dispatch and Visitor Design Pattern.
Related
I am facing an OOP problem in GUI design, but let me illustrate it with animals example. Lets have following setup:
there is a base class Animal
any derived class can has-a Teeth
every animal with Teeth can Bite() <=> animals without Teeth cannot Bite()
every animal Bite() the same way (there is default implementation in Teeth class)
It is only natural for animal has-a Teeth, but now I need something like interface for has-a relationship. For example, if I have a vector of animals, how can I make every Bite() if they can?
std::vector<Animal *> animals;
animals.push_back(new dog());
animals.push_back(new fly());
animals.push_back(new cat());
void Unleash_the_hounds(std::vector<Animal *> animals)
{
//bite if you can!
}
I came up with several solutions but none seems to be perfectly fitting:
1.) every class with Teeth also implements interface IBiting. This solution, however, introduces a lot of code duplication, I would need to "implement" Bite() in every class:
class Cat : public Animal, public IBiting {
Teeth teeth;
public:
virtual void Bite() { teeth.Bite(); }
}
2.) Give every animal Teeth, but only allow some to use them. Note: syntax can be wrong - it is only illustration
class Animal{
static cosnt bool canBite = false;
Teeth teeth;
public:
void Bite() { this->canBite ? teeth.Bite() : return; }
}
class Cat {
static cosnt bool canBite = true;
}
3.) More inheritance - create class BitingAnimal and derive it. Well, this could work, but what if I needed derive (non)flying animals, some of them have teeth.
class Animal{}
class BitingAnimal : public Animal {
Teeth teeth;
}
and use as BitingAnimal.teeth.Bite()
4.) multiple inheritance. This often is discouraged, and impossible in most languages, plus it is not logical for Cat to be Teeth.
class Cat : public Animal, public Teeth {
}
5.) Enum of classes that can bite - weird only by sound of it.
Or am I only over-complicating it and missed something important?
An alternative that you didn't mention is to just provide an abstraction for the teeth, but implement the biting in the base class. This reduces the duplication because the derived classes only need to specify how to access the teeth instead of how to bite. By returning a pointer to the teeth, we can allow a null pointer to indicate that the animal has no teeth. Here is an example:
#include <vector>
struct Teeth {
void bite() { }
};
struct Animal {
virtual Teeth *teethPtr() = 0;
void biteIfYouCan() { if (teethPtr()) teethPtr()->bite(); }
};
struct Dog : Animal {
Teeth teeth;
Teeth *teethPtr() override { return &teeth; }
};
struct Fish : Animal {
Teeth *teethPtr() override { return nullptr; }
};
int main()
{
Dog dog;
Fish fish;
std::vector<Animal *> animals {&dog,&fish};
for (auto animal_ptr : animals) {
animal_ptr->biteIfYouCan();
}
}
1) Interface is good and you can add default implementation this way:
class IBiting { public virtual void bite() = 0 };
class HasTeeth, public IBiting { Teeth teeth; public:
virtual void bite() override { teeth.bite(); } };
for(Animal* a: animals) {
IBiting* it = dynamic_cast<IBiting*>(a);
if(it) it->bite(); }
1b) ...you can as well completly remove the interface and use only HasTeeth:
class HasTeeth { Teeth teeth; public:
void bite() { teeth.bite(); } };
for(Animal* a: animals) {
HasTeeth* it = dynamic_cast<HasTeeth*>(a);
if(it) it->bite(); }
2) Bloating Animal can be used if you don't want to use RTTI/dynamic_cast. You could make virtual void bite() with empty implementation on Animal and override it later (once adding Teeth). Not that much of coding if you insist not to use RTTI, but if you can use dynamic_cast, why not using it?
EDIT: The answer from Vaughn Cato is perfect for this - virtual/abstract teethPtr() (or getTeeth()) in Animal with short-cuts like biteIfYouCan(). Good for embedded world (microchips), but for PC, I still prefer dynamic_cast.
3) Virtual inheritance can help us with BitingAnimal vs. FlyingAnimal:
class BitingAnimal: public virtual Animal {
Teeth teeth; public void bite() { teeth.bite(); } };
class FlyingAnimal: public virtual Animal {
Wings wings; public void fly() { wings.fly(); } };
class FlyingBitingAnimal: /*public virtual Animal, */
public FlyingAnimal, public BitingAnimal {};
4) Joining Animal and Teeth has no sense unless you completely remove Teeth and replace it with HasTeeth or CanBite. Then it becomes my 1b.
5) That enum is another version of 2 - bloating animal. Not good.
But that leads me to alternative not using dynamic_cast: you can mimic it by capabilities (that enum, or flags on animal - bool can_bite) that can tell you, wich cast is safe. Then you can use multiple/virtual inheritance to mimic dynamic_cast (check capability first, cast next).
EDIT: Vaughn Cato's teethPtr() matches this as well (show me the teeth you can bite with if you have them) and does not need the cast.
Answer to comment:
In short: try to name a feature (capability, ability to do something, to provide something).
Long answer: Do you need Teeth and HasTeeth or single CanBite? Your 4th solution is not bad in the principle, but in naming and therefore other possibilities. All this was hypothetical. Interfaces are well known in other languages (single inheritance + interfaces), HasTeeth is something like C# IListSource with IList GetList() and bool ContainsList (for erasure) where the bite() is not there directly, but can be added by extension method:
static IEnumerator GetEnumerator(this IListSource it) {
if(!it.ContainsList) yield break;
foreach(object o in it.GetList()) yield return o; }
Here you can see, that I have achieved same thing with C# extension method as with C++ multiple inheritance. The name is is-a form - SourceOf. Can you share the real names from your GUI with us?
Example from C++ would be iostream = istream + ostream with virtual inheritance from ios. Again is-a naming.
Here are my comments to your solutions:
I agree with you that this will result in a lot of code duplication. Not cool.
This clearly isn't the best way. Using canBite flag is a symptome, that it can be done better.
Again, bad design - calling BitingAnimal.teeth.Bite() is a violation of Law of Demeter. Also, as you described - what if an Animal which is not BittingAnimal would like to bite?
As Mare Infinitus commented, in this approach your Cat is a Teeth. This is not entirely correct.
Enum of classes that can bite - you're right. This is weird :)
I'd suggest following approach: create IBiting interface and its implementation Biting in a mixin-like way:
class Bitting : public IBiting {
Teeth teeth;
public:
virtual void Bite() { teeth.Bite(); }
}
then, each class which can bite, will inherit from Biting "mixin":
class Cat : public Animal, public Biting {
}
This will be a multiple inheritance, of course, but, since Biting only implements a "Biting" functionality, it won't be so bad (no Diamond Problem).
The question boils down to what should happen if you call animal->bite() and that animal does not have teeth and cannot bite. One answer could be that all animals can bite. For cats it has an effect due to them having teeth whereas other animals such as butterflies can bite but nothing happens.
class Animal{
public:
virtual void bite(){}
};
class Cat : public Animal{
Teeth teeth;
void bite() override{
teeth.bite();
}
};
class Butterfly : public Animal{
};
In this approach you do need to write for every animal type extra how it bites if it can. It becomes a bit more tricky if you need other attributes like scream() and fly(). Yes cats can fly in this model, it is just that nothing at all happens when they do and butterflies can scream with a volume of zero.
Since there are a lot of animals who have teeth and they all bite the same way you could add a few specialized animals.
class BitingWithTeethAnimal : public Animal{
Teeth teeth;
void bite() override{
teeth.bite();
}
};
class Cat : public BitingWithTeethAnimal{
};
class Butterfly : public FlyingWithWingsAnimal{
};
Ideally you would be able to say something like class Pterodactyl : public BitingWithTeeth, FlyingWithWings, ScreamingWithVoice, Animal; without bloating Animal to a monster class but that is not possible in my implementation. The upside though is that you only implement the things you need and you never get confused when an animal can bite with its teeth and also with its beak since the implementation is in one function and not separated in different classes.
This answer is no longer valid, once we made clear that:
every animal with Teeth can Bite() <=> animals without Teeth cannot Bite()
This leads to less separation. There are better answers, but I have undeleted this one to show my thoughts about the design:
Original:
class Animal { public: virtual ~Animal() {} /* for RTTI */ };
class IBite { virtual void Bite() = 0; }; // interface
class Teeth: public IBite { public: void Bite() { ... } }; // implementation
class HasTeeth { protected: Teeth teeth; }; // part of thought process
class BiteWithTeeth: public HasTeeth, public IBite { // interface
public: void Bite() { teeth.Bite(); } }; // +implementation
class Cat: public Animal, public BiteWithTeeth {}; // final class
class Unknown: public Animal, public HashTeeth {}; // but no IBite - not allowed
The order above should make you think why. It involves using dynamic_cast to find the interface (solution will be different if you insist not using it). I prefer to separate things that are not related and find the smallest things (classes/interfaces) that are truly related (otherwise you will do that later when you find that you need it - if you ever need to separate bite from teeth).
class AnimalBitingWithTeeth: public Animal, public BiteWithTeeth {};
class AnimalWithTeethButNotBiting: public Animal, public HashTeeth {};
We need Animal as base class and IBite (or IBiting) to mark some feature. Other classes allow us to implement that feature (e.g. BiteWithTeeth) but allow other implementations as well.
Important question is: Can we have a chain where IBite will be included but we want to disable it then? We can reimplement (virtual) Bite with empty or add virtual bool CanBite() if we need to ask such question (instead of bite if you can). It is crutial to find correct questions (and features) in OOP to create good design.
See my second answer for the solution - multiple/virtual inheritance.
It's a code smell to put things into the same container that don't share something.
Query for the right container instead of query the class of it's capabilities.
If you really want to have a single creating instance use a helper class. But try to use interfaces for classes that have something in common. Imagine if you have 5000 animal types and two of them can bite. Do you really want to look through each of them to go an check each of them for teeth? You already know you only have two dogs at the time you acquire them.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
struct Animal { virtual ~Animal() {} }; // used to tag elements
struct Biting : public Animal { virtual void bite() = 0; };
struct Flying : public Animal { virtual void fly() = 0; };
struct Bird : public Flying {
virtual void fly() override { cout << "Fly\n"; }
};
struct Dog : public Biting {
virtual void bite() override { cout << "Bite\n"; }
};
struct World {
void populate(Animal *animal) {
Biting *b = dynamic_cast<Biting *>(animal);
if (b != nullptr) {
Biters.push_back(b);
return;
}
Flying *f = dynamic_cast<Flying *>(animal);
if (f != nullptr) {
Flyers.push_back(f);
return;
}
}
std::vector<Biting *> Biters;
std::vector<Flying *> Flyers;
};
class Schaefer : public Dog { };
class Pitbull : public Dog { };
class KingFisher : public Bird { };
class WoodPecker : public Bird { };
int main(int argc, char **argv) {
World w;
Schaefer s;
Pitbull p;
KingFisher k;
WoodPecker wp;
w.populate(&s);
w.populate(&p);
w.populate(&k);
w.populate(&wp);
for (auto &i : w.Biters) {
i->bite();
}
for (auto &i : w.Flyers) {
i->fly();
}
return 0;
}
You have an animal Shelter. Shelter can store variable number of Animals. You put many Animals (Dogs and Cats) into the shelter.
Then you tell the employee to randomly select and bring you few Animals. You don't know what type of an Animal he selected.
You tell them to Speak. Some of them goes "bark", some goes "meow".
Important! Dogs can fetch and Cats can't.
If you know for sure you've selected a Dog it should be able to fetch right away (without upcasting from Animal to Dog for example)
How to implement this kind of logic? (preferably without boost::any)
Here is a partially working example: http://ideone.com/kR4788
#include <iostream>
#include <map>
using namespace std;
class Animal {};
class Shelter {
private:
std::map<int, Animal*> animals;
public:
void Add(Animal* animal) {
animals[animals.size()] = animal;
};
Animal* Select(int index) {
return animals[index];
}
};
class Dog: public Animal {
public:
void Speak() { cout << "bark" << endl; }
void Fetch() {}
};
class Cat: public Animal {
public:
void Speak() { cout << "meow" << endl; }
};
Shelter shelter;
int main() {
shelter.Add(new Cat());
shelter.Add(new Dog());
// I'd like to make it work like this
//
// shelter.Select(0)->Speak(); /* meow */
// shelter.Select(1)->Speak(); /* bark */
//
// Like below but without upcasting to given animal
((Cat*) shelter.Select(0))->Speak();
((Dog*) shelter.Select(1))->Speak();
// I know under index 1 is a Dog so it can fetch!
//
// shelter.Select(1)->Fetch(); /* no segfault */
//
// Like below but without upcasting to given animal
((Dog*) shelter.Select(1))->Fetch();
return 0;
}
Edit:
You can try to use a dynamic_cast to cast your Animal object into a Dog and then call the fetch method:
Dog *foo = dynamic_cast<Dog*>(shelter.Select(1));
if (foo) {
foo->Fetch();
}
If the dynamic_cast fails, it will return null so make sure to check if the object is not null before using it. For more information on dynamic_cast, check here.
You can add a virtual function to your Animal interface:
class Animal {
public:
virtual void speak();
};
Also, on an unrelated note, your speak method doesn't seem to be modifying the object so you should consider putting them as const:
class Animal {
public:
virtual void speak() const;
};
You can find more information on const-correctness here.
As Aliou noticed speak should be declared virtual in Animal, otherwise the hierarchy is rather useless, or, in other words, there is no polymorphism.
Testing if an Animal is a Dog (and upcasting at the same time) with dynamic_cast<Dog*> is an option to consider. Not pretty, but it works.
Dog *dog = dynamic_cast<Dog*> shelter.Select(1);
if (dog) dog->Fetch();
(dynamic_cast to a pointer never throws, as others suggested...)
Another solution is to define virtual Fetch in Animal, perhaps as a NOP ({}), so you don't have to define it in animals which don't fetch.
As per request I post my comment as an answer. The full source is in Ideone:
In class Animal:
class Animal {
public:
virtual void Speak() const = 0;
virtual void Fetch() const { cout << "This animal can't fetch" << endl;};
virtual ~Animal(){ }
};
The virtual destructor is needed to ensure that the correct destructor is called for objects that derive from the base class. Without the virtual destructor only the base class destructor would be called and not the destructor for the derived object.
In Dog:
void Fetch() const { cout << "fetch" << endl; }
And in main:
shelter.Select(0)->Speak();
shelter.Select(1)->Speak();
shelter.Select(0)->Fetch();
shelter.Select(1)->Fetch();
You didn't ask the employee to return only animals which could fetch, therefore you must check (cast) each animal can fetch.
The alternative is to add a dummy fetch function to animal, which doesn't do anything except for dogs.
I would like the experts here to have an opinion on the following problem. I would like to design a program in which derived classes from different base classed interact with each other. To make my point clear, I have constructed an example.
Imagine that I try to make a zoo. In this zoo we have animals, and we have fruits, which are my base classes. Only during runtime we know which animals we have, and which fruits. Assume that I have a monkey and a banana.
How do I let this monkey consume a banana in an elegant way, where eating a banana is a very unique skill of this monkey only? Note that I don't want a generic eat function, because I need in my design total freedom in the actions that a derived animal can perform.
This is the accompanying example:
#include <string>
#include <iostream>
class cfruit
{
};
class cbanana : public cfruit
{
};
class canimal
{
};
class cmonkey : public canimal
{
public:
int eatbanana(cbanana *) { std::cout << "BURP" << std::endl; }
};
int main()
{
cfruit *fruit;
canimal *animal;
// on runtime the animal and the fruit is decided, so we have to
// initialize it on the base pointer
// assume we get a monkey and a banana
fruit = new cbanana();
animal = new cmonkey();
// now, we would like our monkey to eat a banana, which we cannot do...
// UNLESS... we do something really UGLY
static_cast<cmonkey *>(animal)->eatbanana(static_cast<cbanana *>(fruit));
return 0;
}
You are asking us a way to violate the Liskov Principle "elegantly".
When you manipulate a mother class, you should not assume of the concrete derived class that is instanciated behind.
This is called bad design, coding smell.
If your class is indeed a monkey, and you want it to eat bananas: you should not manipulate it as an animal, but as a monkey.
A track to find a solution anyway could start this way:
As you explain, there is an implicit link between animals and their fruit. You could create a class Meal which goal is to manage this link explicitely.
struct Meal
{
virtual void consume() = 0;
}
Meal* factoryCookMonkeyMeal(Monkey& monkey, Banana& banana)
{
return new MealMonkey(monkey,banana);
}
struct MealMonkey : public Meal
{
Monkey& monkey;
Banana& banana;
virtual void consume(){ monkey.eat_banana(banana);};
}
Meal* factoryCookBirdMeal(Bird& bird, Cherry& cherry)
{
return new MealBird(bird,cherry);
}
struct MealBird : public Meal
{
Bird& bird;
Cherry& cherry;
virtual void consume(){ bird.eat_cherry(cherry);};
}
However you don't tell us precisely the way you determine the animal and the fruit... so that doesn't help... because it is this choice that knows the info that must be used for calling the good factoryMethod that creates the appropriate meal.
This is an example of a problem I have while designing an interface.
I have a class Animal and I have derived Cat, Dog and Lion from it. Now I have a function 'feedFood' which takes in the base class Animal as parameter. Based on the type of animal I should feed different food to the Animal.
So how do I check the type of the animal in the 'feedFood' function.
There are 3 methods I could think of
Adding a 'AnimalType' enum in the base class which is set to the right type in the derived class.
Add a virtual function in base class to return a string with animal type. In derived class return the proper string for the animal name.
Use typeid or dynamic_cast to check the type of the derived class in the 'feedFood' function.
Which is the best method or is there any other better approach for this?
You are currently saying this:
void feedFood(Animal &);
Cat myCat;
Dog myDog;
feedFood(myCat);
feedFood(myDog);
// Problem: How does feedFood() know what's going on?
To use polymorphism, make the feeding function a virtual member of Animal:
struct Animal
{
virtual void feedFood() = 0; // pure virtual or default behaviour, up to you
virtual ~Animal() { } // always provide virtual destructor!
/* ... */
};
struct Cat : public Animal
{
void feedFood() { /* Cat implementation */ }
/* ... */
};
// Usage:
// via reference
void feed(Animal & a) { a.feedFood(); }
// via pointer
Animal * b = new Bat;
b->feedFood();
Try this:
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};
class Lion: public Animal{};
void FeedFood(Dog& d)
{
cout << "Feeding the dog.\n";
return;
}
void FeedFood(Cat& c)
{
cout << "Feeding the cat.\n";
return;
}
void FeedFood(Lion& l)
{
cout << "Feeding the lion.\n";
}
void FeedFood(Animal& a)
{
cout << "Feeding an unknown animal.\n";
return;
}
With the above functions, the compiler will take care of feeding animals.
Sometimes, functionality may be better placed outside the class.
Okay, somewhat complicated, but resolves at compile time:
template <class _Derived>
class Animal
{};
class Dog: public Animal<Dog>
{
public:
void Feed()
{
cout<<"Feeding Dog...";
}
};
class Cat: public Animal<Cat>
{
public:
void Feed() { /* Feed Cat*/ }
};
And implement ONE template function:
template<class _AnimalType>
void FeedAnimal(_AnimalType& animal)
{
animal.Feed();
}
Create instance of any class, and call FeedAnimal:
Dog dog;
Cat cat;
FeedAnimal(dog);
FeedAnimal(cat);
If Feed is not implemented by derived-class, you may not get error, until you call Feed template function. Therefore, if Lion is implemented like:
class Lion : public Animal<Lion>
{};
You won't get any error that Feed is missing from class. As soon as you make call to FeedAnimal with Lion, you would get error that Lion is missing Feed method.
This is one of the hack to ensure that derived class implements Feed:
template <class _Derived>
class Animal
{
void (_Derived::*pDummy)();
public:
Animal()
{
pDummy = &_Derived::Feed;
}
};
Dirty, but works!
Not the animal gets food feeded, but it ates it. So add a virtual 'eat' method together with some FoodProvider on which the Animal can eat on.
Update:
So instead of an
void feed (const Food & food);
use
virtual void eatFrom (FoodProvider * provider);
That way you can also implement different food resources in your provider.
I am attempting to create something like this:
class food
{
public:
void EAT(); //Whatever happens...
int bitesLeft //This is decreased by one each time you eat the food
};
class cheese: public food
{
public:
void EAT(); //Some overloaded form of the "eat" command...
};
Is there a way to create one of each at runtime, and have a function that can take either one as arguments without screwing up the bitesLeft variable of each one?
I'm assuming you want something like:
function doStuff(food * f) {
f->EAT();
}
And you want this to call the specialised EAT if a cheese is passed in, or the non-specialised form if a food is passed in. In this case, you need a virtual function:
class food {
public:
virtual void EAT();
virtual ~food(); // Any class being used polymorphically should have
// a virtual destructor
}
class cheese : public food {
public:
virtual void EAT();
}
I'm not exactly sure what you mean by 'without screwing up the bytesLeft variable. This is a public data member, so it's possible for any code to modify the value of the variable in ways you weren't expecting. This includes code in the cheese class, but also code that's not in either of the classes.
If you want to prevent code in the cheese.EAT method from modifying the bitesLeft member then you should declare it as private in the base class.
Yes, there is:
void myfunc(food* f)
{
f->EAT();
}
int main()
{
food f;
cheese c;
myfunc(&f);
myfunc(&c);
return 0;
}
However, for this to work, you need to declare EAT() as virtual in the food class, as in virtual void EAT();. Also, you probably want to declare bitesLeft as protected, so that only the class itself as well as the subclasses can access it.
The member variables of two objects are separate. This code works as you expect:
void AFunction( food& x ) {
x.EAT();
}
food a;
a.bitesLeft = 10;
cheese b;
b.bitesLeft = 5;
AFunction(a); // a.bitesLeft --> 9
AFunction(b); // b.bitesLeft --> 4