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.
Related
I am revising the Visitor pattern I used some time ago. We have base class Element which has virtual method accept(Visitor) and this method is overridden in all classes inheriting from Element. And all that accept() does in any derived class is to call visitor->visit(*this). Now when the client runs the code, he/she does for example:
Visitor& theVisitor = *new ConcreteVisitor();
for_each(elements.begin(), elements.end(), [](Element& e) { e.accept(theVisitor));})
Why the client cannot just call visitor->visit(element) like this:
Visitor& theVisitor = *new ConcreteVisitor();
for_each(elements.begin(), elements.end(), [&theVisitor](Element& e) { theVisitor.visit(e); });
What useful information is in calling element.accept(visitor) which in turns calls visitor.visit(element)? This makes the usage of the Visitor pattern cumbersome and requires extra code in all the hierarchy of Element classes.
So can someone explain benefits of accept() here?
I've been long confused with the Visitor pattern and I've been trying to find explanations all over the Internet and these explanations confused me even more. Now I realised the reasons why Visitor pattern is needed and the way how it is implemented, so here it is:
Visitor pattern in needed to solve the Double Dispatch problem.
Single dispatch - when you have one class hierarchy and you have an instance of a concrete class in this hierarchy
and you want to call an appropriate method for this instance. This is solved with function overriding (using virtual function table in C++).
Double dispatch is when you have two class hierarchies and you have one instance of concrete class from one hierarchy and one instance of concrete class from the other hierarchy and you want to call the appropriate method which will do the job for those two particular instances.
Let's look at an example.
First class hierarchy: animals. Base: Animal, derived: Fish, Mammal, Bird.
Second class hierarchy: invokers. Base: Invoker, derived: MovementInvoker (move the animal), VoiceInvoker (makes the animal to sound), FeedingInvoker (feeds the animal).
Now for every specific animal and every specific invoker we want just one specific function to be called that will do the specific job (e.g. Feed the Bird or Sound the Fish). So altogether we have 3x3 = 9 functions to do the jobs.
Another important thing: the client who runs each of those 9 functions does not want to know what concrete Animal and what concrete Invoker he or she has got at hand.
So the client wants to do something like:
void act(Animal& animal, Invoker& invoker)
{
// Do the job for this specific animal using this specific invoker
}
Or:
void act(vector<shared_ptr<Animal>>& animals, vector<shared_ptr<Invoker>>& invokers)
{
for(auto& animal : animals)
{
for(auto& invoker : invokers)
{
// Do the job for this specific animal and invoker.
}
}
}
Now: how is it possible in RUN-TIME to call one of the 9 (or whatever) specific methods that deals with this specific Animal and this specific Invoker?
Here comes Double Dispatch. You absolutely need to call one virtual function from first class hierarchy and one virtual function from the second.
So you need to call a virtual method of Animal (using virtual function table this will find the concrete function of the concrete instance in the Animal class hierarchy) and you also need to call a virtual method of Invoker (which will find the concrete invoker).
YOU MUST CALL TWO VIRTUAL METHODS.
So here is the implementation (you can copy and run, I tested it with g++ compiler):
visitor.h:
#ifndef __VISITOR__
#define __VISITOR__
struct Invoker; // forward declaration;
// -----------------------------------------//
struct Animal
{
// The name of the function can be anything of course.
virtual void accept(Invoker& invoker) = 0;
};
struct Fish : public Animal
{
void accept(Invoker& invoker) override;
};
struct Mammal : public Animal
{
void accept(Invoker& invoker) override;
};
struct Bird : public Animal
{
void accept(Invoker& invoker) override;
};
// -----------------------------------------//
struct Invoker
{
virtual void doTheJob(Fish& fish) = 0;
virtual void doTheJob(Mammal& Mammal) = 0;
virtual void doTheJob(Bird& Bird) = 0;
};
struct MovementInvoker : public Invoker
{
void doTheJob(Fish& fish) override;
void doTheJob(Mammal& Mammal) override;
void doTheJob(Bird& Bird) override;
};
struct VoiceInvoker : public Invoker
{
void doTheJob(Fish& fish) override;
void doTheJob(Mammal& Mammal) override;
void doTheJob(Bird& Bird) override;
};
struct FeedingInvoker : public Invoker
{
void doTheJob(Fish& fish) override;
void doTheJob(Mammal& Mammal) override;
void doTheJob(Bird& Bird) override;
};
#endif
visitor.cpp:
#include <iostream>
#include <memory>
#include <vector>
#include "visitor.h"
using namespace std;
// -----------------------------------------//
void Fish::accept(Invoker& invoker)
{
invoker.doTheJob(*this);
}
void Mammal::accept(Invoker& invoker)
{
invoker.doTheJob(*this);
}
void Bird::accept(Invoker& invoker)
{
invoker.doTheJob(*this);
}
// -----------------------------------------//
void MovementInvoker::doTheJob(Fish& fish)
{
cout << "Make the fish swim" << endl;
}
void MovementInvoker::doTheJob(Mammal& Mammal)
{
cout << "Make the mammal run" << endl;
}
void MovementInvoker::doTheJob(Bird& Bird)
{
cout << "Make the bird fly" << endl;
}
// -----------------------------------------//
void VoiceInvoker::doTheJob(Fish& fish)
{
cout << "Make the fish keep silence" << endl;
}
void VoiceInvoker::doTheJob(Mammal& Mammal)
{
cout << "Make the mammal howl" << endl;
}
void VoiceInvoker::doTheJob(Bird& Bird)
{
cout << "Make the bird chirp" << endl;
}
// -----------------------------------------//
void FeedingInvoker::doTheJob(Fish& fish)
{
cout << "Give the fish some worms" << endl;
}
void FeedingInvoker::doTheJob(Mammal& Mammal)
{
cout << "Give the mammal some milk" << endl;
}
void FeedingInvoker::doTheJob(Bird& Bird)
{
cout << "Give the bird some seed" << endl;
}
int main()
{
vector<shared_ptr<Animal>> animals = { make_shared<Fish> (),
make_shared<Mammal> (),
make_shared<Bird> () };
vector<shared_ptr<Invoker>> invokers = { make_shared<MovementInvoker> (),
make_shared<VoiceInvoker> (),
make_shared<FeedingInvoker> () };
for(auto& animal : animals)
{
for(auto& invoker : invokers)
{
animal->accept(*invoker);
}
}
}
Output of the above code:
Make the fish swim
Make the fish keep silence
Give the fish some worms
Make the mammal run
Make the mammal howl
Give the mammal some milk
Make the bird fly
Make the bird chirp
Give the bird some seed
So what happens when the client has got an instance of Animal and an instance of Invoker and calls animal.accept(invoker)?
Suppose that the instance of Animal is Bird and the instance of Invoker is FeedingInvoker.
Then thanks to virtual function table Bird::accept(Invoker&) will be called which will in turn run invoker.doTheJob(Bird&).
As Invoker instance is FeedingInvoker, virtual function table will use FeedingInvoker::accept(Bird&) for this call.
So we made the double dispatch and called the correct method (one of 9 possible methods) for Bird and FeedingInvoker.
Why is Visitor pattern good?
The client does not need to depend on both complex class hierarchies of Animals and Invokers.
If new concrete animal (say, Insect) needs to be added, no existing Animal hierarchy needs to be changed.
We only need to add: doTheJob(Insect& insect) to Invoker and all derived invokers.
Visitor pattern elegantly implements the open/closed principle of object-oriented design: the system should be open to extensions and closed to modifications.
(In classic Visitor pattern Invoker would be replace by Visitor and doTheJob() by visit(), but to me these names don't actually reflect the fact that some job is done on elements).
I apologize if this has been answered before but I've been looking for hours. Here is a contrived example of what I am trying to do.
#include <iostream>
using namespace std;
int main(void);
class humanoid {
public:
int humanoid_attribute;
virtual void do_something_to_any_humanoid(void) = 0;
};
class man: public humanoid {
public:
int man_attribute;
void do_something_to_any_humanoid(void) { cout << "Doing something to a man which is a humanoid.\n"; }
};
class cat {
public:
int cat_attribute;
virtual void do_something_to_any_cat(void) = 0;
};
class lion : public cat {
public:
int lion_attribute;
void do_something_to_any_cat(void) { cout << "Doing something to a lion which is a cat.\n"; }
};
class sphinx : public humanoid, public cat {
public:
int sphinx_attribute;
sphinx(humanoid & humanoidIn, cat & catIn) : humanoid(humanoidIn), cat(catIn) { }
};
int main(void) {
man myMan;
lion myLion;
sphinx mySphinx(myMan, myLion);
mySphinx.do_something_to_any_humanoid();
}
The problem is that when instantiating a sphinx I get the following errors:
./main.cpp: In function ‘int main()’:
./main.cpp:41:9: error: cannot declare variable ‘mySphinx’ to be of abstract type ‘sphinx’
sphinx mySphinx(myMan, myLion);
^
./main.cpp:31:7: note: because the following virtual functions are pure within ‘sphinx’:
class sphinx : public humanoid, public cat {
^
./main.cpp:22:15: note: virtual void cat::do_something_to_any_cat()
virtual void do_something_to_any_cat(void) = 0;
^
./main.cpp:10:15: note: virtual void humanoid::do_something_to_any_humanoid()
virtual void do_something_to_any_humanoid(void) = 0;
I understand what the error says but can't figure out the proper way to do it. I do have a valid use for this and yes, 'sphinx' is both some sort of humanoid and some sort of feline and should inherit all their attributes and methods. Also, the 'man' and 'lion' need to be children so I can make an ugly sphinx. Can you picture a klingon and a persian?
Inheritance expresses the is-a relationship.
If a sphinx is both a humanoid and a cat then the type must be able to be used in all contexts in which a humanoid or a cat is required. Since these two types have two pure virtual methods then you must provide implementations for such methods.
First of all, we should look at what you're attempting to achieve: abstract base classes working as interfaces to blueprint methods that objects of non-abstract leaf classes can dispatch.
For this purpose, lets leave the class variables out of it, and focus on an example with only class methods:
#include <iostream>
/* astract base classes */
/* -------------------- */
class Humanoid {
public:
virtual ~Humanoid() = 0;
// Pure virtual; ensures Humanoid is abstract, even in case we supply
// default implementations for all "blueprinted" method (not the case
// for the Humanoid type, but for the Cat type)
// no default implementation supplied: derived classes
// must implement this method in order to be non-abstract
virtual void doSomethingToAnyHumanoid() = 0;
};
Humanoid::~Humanoid() {}
class Cat {
public:
virtual ~Cat() = 0; // Pure virtual; ensures Cat is abstract ...
// supply a default implementation
virtual void doSomethingToAnyCat() {
std::cout << "Cat default implementation\n";
}
};
Cat::~Cat() {}
These two base classes are abstract as they have at least one pure virtual method (in the case of Cat, only its DTOR).
As a first attempt, we'll try to implement a sphinx class that is common leaf class of Humanoid as well as Cat:
/* non-abstract leaf classes */
/* ------------------------- */
class NotReallyASphinx : public Humanoid, public Cat {
public:
// by choice (not necessity): use default cat implementation
// for non-abstractness: implement custom Humanoid implementation
virtual void doSomethingToAnyHumanoid() override {
std::cout << "Needs to be done on four legs ...\n";
}
};
/* example usage */
int main() {
NotReallyASphinx notReallyASphinx;
notReallyASphinx.doSomethingToAnyHumanoid(); // Needs to be done on four legs ...
notReallyASphinx.doSomethingToAnyCat(); // Cat default implementation
return 0;
}
Since Humanoid provides no default implementation of doSomethingToAnyHumanoid, its a necessity that we implement it in NotReallyASphinx, in order for the latter to be non-abstract.
Now, for your slightly more sphinx-like attempt at a sphinx, it seems you want to make use of a Lion and a Man instance (wrapped, however, in addresses of their abstract base classes) to construct the basis for an UglySphinx. Lets start by implementing the minimal non-abstract types Lion and Man:
/* non-abstract leaf classes */
/* ------------------------- */
class Man: public Humanoid {
public:
virtual void doSomethingToAnyHumanoid() override {
std::cout << "Doing something to a man which is a humanoid.\n";
}
};
class Lion : public Cat {
public:
virtual void doSomethingToAnyCat() override {
std::cout << "Doing something to a lion which is a cat.\n";
}
};
If you, however, want to construct an UglySphinx based on instances of the two types above, you need to resort to type composition: where and UglySphinx instance in itself owns (responsibility of) instances of Lion and Man.
/* non-abstract leaf classes */
/* ------------------------- */
class UglySphinx : public Humanoid, public Cat {
private:
Humanoid& m_humanoid;
Cat& m_cat;
// we know that humanoidIn and catIn will persist at least
// as long as the UglySphinx instance, so we'll just work
// on the stack for this example. An alternative is using
// pointers here and working on heap; which includes responsibility
// handling of the heap objects (e.g. owned by UglySphinx)
public:
UglySphinx(Humanoid& humanoidIn, Cat& catIn) : m_humanoid(humanoidIn), m_cat(catIn) { }
// by choice (not necessity): use dynamic dispatch to use the
// m_cat(lion) implementation
virtual void doSomethingToAnyCat() override {
m_cat.doSomethingToAnyCat();
}
// for non-abstractness: we must implement custom Humanoid implementation,
// but as above, use m_humanoid(man) for this purpose
virtual void doSomethingToAnyHumanoid() override {
m_humanoid.doSomethingToAnyHumanoid();
}
};
Which would allow us to construct an UglySphinx using a Man and a Lion object:
/* example usage */
int main() {
Man aMan;
Lion aLion;
UglySphinx uglySphinx(aMan, aLion);
uglySphinx.doSomethingToAnyHumanoid(); // Doing something to a man which is a humanoid.
uglySphinx.doSomethingToAnyCat(); // Doing something to a lion which is a cat.
return 0;
}
Since you're intent on working with addresses (alternative pointers) of the abstract base class types, the UglySphinx type above would allow us to create an (really) UglySphinx instance based on e.g. a Man instance and say, a RagDoll:
/* non-abstract leaf classes */
/* ------------------------- */
class RagDoll : public Cat {
public:
virtual void doSomethingToAnyCat() override {
std::cout << "Doing something to a ragdoll which is a cat.\n";
}
};
/* example usage */
int main() {
Man aMan;
RagDoll aRagdoll;
UglySphinx reallyUglySphinx(aMan, aRagdoll);
reallyUglySphinx.doSomethingToAnyHumanoid(); // Doing something to a man which is a humanoid.
reallyUglySphinx.doSomethingToAnyCat(); // Doing something to a ragdoll which is a cat.
return 0;
}
I can't see the risk of creating ragdoll-based Sphinx being intentional, so perhaps what you really wanted to do was create a PersistantUglySphinx which is guaranteed to be composed of Man and Lion instances (w.r.t. the methods doSomethingToAnyHumanoid() and doSomethingToAnyCat(), respectively)?
/* non-abstract leaf classes */
/* ------------------------- */
class PersistantUglySphinx : public Man, public Lion {
private:
Man m_man;
Lion m_lion;
public:
PersistantUglySphinx(Man& manIn, Lion& lionIn) : m_man(manIn), m_lion(lionIn) { }
virtual void doSomethingToAnyCat() override {
m_lion.doSomethingToAnyCat();
}
virtual void doSomethingToAnyHumanoid() override {
m_man.doSomethingToAnyHumanoid();
}
};
Just beware that with this approach we've run into an possibly best-practices issue. Since PersistantUglySphinx derives from Man and Lion, the two latter types are no longer leaf classes, but nor have they been made abstract. Especially when working with "interface"-like inheritance as in this example, I at least personally try to adhere to Scott Meyers advice that we should "Make non-leaf classes abstract" (Item 33 from "More Effective C++").
To wrap it up: make sure to understand what an abstract class is, and what is required of a class derived from an abstract class to be non-abstract (i.e., implementations of all pure virtual methods of the abstract base class).
#dfri : My intention is code like this:
#include <iostream>
using namespace std;
int main(void);
class Humanoid {
private:
int HumanoidAttribute;
public:
// pure virtual to ensure all derived classes define it
virtual void doSomethingToAnyHumanoid(void) = 0;
// pure virtual to ensure this is an abstract class
// not really necessary because doSomethingToAnyHumanoid is pure virtual but good practice
virtual ~Humanoid() = 0;
};
Humanoid::~Humanoid() { }
class Man: public Humanoid {
private:
int ManAttribute;
public:
void doSomethingToAnyHumanoid(void) override {
cout << "Doing something to a Man which is a Humanoid.\n";
}
};
class Cat {
private:
int CatAttribute;
public:
// pure virtual to ensure all derived classes define it
virtual void doSomethingToAnyCat(void) = 0;
// pure virtual to ensure this is an abstract class
// not really necessary because doSomethingToAnyCat is pure virtual but good practice
virtual ~Cat() = 0;
};
Cat::~Cat() { }
class Lion : public Cat {
private:
int LionAttribute;
public:
void doSomethingToAnyCat(void) override {
cout << "Doing something to a Lion which is a Cat.\n";
}
};
class Sphinx : public Humanoid, public Cat {
private:
Humanoid & m_Humanoid;
Cat & m_Cat;
int SphinxAttribute;
public:
Sphinx(Humanoid & HumanoidIn, Cat & CatIn) : m_Humanoid(HumanoidIn), m_Cat(CatIn) { }
void doSomethingToAnyHumanoid(void) { m_Humanoid.doSomethingToAnyHumanoid(); }
void doSomethingToAnyCat(void) { m_Cat.doSomethingToAnyCat(); }
};
int main(void) {
Man myMan;
Lion myLion;
Sphinx mySphinx(myMan, myLion);
mySphinx.doSomethingToAnyHumanoid();
}
Since the methods of the base classes are pure virtual I should always notice when compiling the Sphinx class if I'm missing some wrapper methods.
Anyone have any other comments? I'm new to C++ so any tips are welcome!
I am trying to implement the strategy design pattern as an exercise. My classes are pretty simple:
1) Fly.cpp
class Fly
{
public:
Fly();
bool fly();
};
class CanFly : public Fly
{
public:
bool fly()
{
return true;
}
};
class CantFly : public Fly
{
public:
bool fly()
{
return false;
}
};
2) Animal.cpp
class Fly;
class Animal
{
Fly myFly;
public:
Animal(Fly f);
void setFly(Fly f);
Fly getFly();
};
Animal::Animal(Fly f)
{
myFly = f;
}
void Animal::setFly(Fly f)
{
myFly = f;
}
Fly Animal::getFly()
{
return myFly;
}
3) Dog.cpp
#include <iostream>
using namespace std;
class Animal;
class Dog : public Animal
{
public:
Dog(Fly f);
};
Dog::Dog(Fly f)
{
setFly(f);
cout << "Dog : " << getFly().fly() << endl;
}
4) Bird.cpp
#include <iostream>
using namespace std;
class Animal;
class Bird : public Animal
{
public:
Bird(Fly f);
};
Bird::Bird(Fly f)
{
setFly(f);
cout << "Bird : " << getFly().fly() << endl;
}
5) AnimalTest.cpp
#include <iostream>
using namespace std;
class Dog;
class Bird;
class CanFly;
class CantFly;
int main()
{
Fly f1 = new CanFly();
Fly f2 = new CantFly();
Bird b(f1);
Dog d(f2);
return 0;
}
The error which I get upon building the code is :
Animal.cpp:5:6: error: field 'myFly' has incomplete type 'Fly'
Fly myFly;
^
Can anyone help me why?
Thanks
Incomplete type error means that compiler doesn't see definition of the class, only declaration.
If you create an object or if you pass an object by value then you need to provide a definition of the class to the compiler. You do create objects and pass them around by values hence you need to include definition of relevant classes you pass into cpp files.
But that is not what you really want to do.
Your intention is to employ polymorphism so you need to pass objects by reference or by pointer instead.
Your Animal class should be:
class Animal
{
Fly &myFly;
public:
Animal(Fly &f);
void setFly(Fly &f);
Fly const &getFly();
};
That way you can pass any of Fly, CanFly, or CantFly objects into Animal object.
You also need to reorganise your code. You need to separate class definitions into header files. For example:
//Animal.h
class Fly; <=== Declaration. OK here.
class Animal
{
Fly &myFly;
public:
Animal(Fly &f);
void setFly(Fly &f);
Fly const &getFly();
};
Then you need to include headers into cpp. Example:
#include "Animal.h"
class Dog : public Animal <=== Compiler needs definition of Animal here
{
public:
Dog(Fly f);
};
Note the difference between following definitions:
Fly Animal::getFly()
{
return myFly;
}
Returns a copy of object stored in myFly.
Fly const &Animal::getFly()
{
return myFly;
}
Returns a constant reference to an object myFly
Also, perhaps, you do not need Fly, CanFly, CantFly classes at all. Classes Bird, Dog already "know" if they can or cannot fly. Sure, you are doing an exercise but still Fly, CanFly, etc seem to be redundant and artificial here.
In order to use a class, its definition is required. A statement like
class Fly;
is not a definition, but merely a declaration. A class that has been declared cannot be used, but you can define pointers and references to such a class.
So, to get your code working, you should split the code into header files (.hpp) containing the class definitions and source files (.cpp) containing the (non-inline) definitions of any class members declared in the headers.
Moreover, you seem to want to use polymorphism, but forgot to declare the member bool Fly::fly() to be virtual. I think what you want is
// file Fly.hpp
struct Fly
{
virtual bool fly() const = 0;
};
struct CanFly : Fly
{
bool fly()
{ return true; }
};
struct CantFly : Fly
{
bool fly()
{ return false; }
};
and then
// file Animal.hpp
struct Fly; // forward declaration
struct Animal
{
const Fly*const myFly; // use pointer to forwardly declared class
// const data member is public (serves as getter)
bool fly() const;
protected:
Animal(Fly const&f);
// no setter: an Animal cannot change its flying behaviour
};
and
// file Animal.cpp
#include "Fly.hpp"
#include "Animal.hpp"
Animal::Animal(Fly const&f)
: myFly(&f) {}
bool Animal::fly() const
{ return myFly->fly(); } // polymorphic call
However, I don't like this pattern. The problem is that in order to define a Bird or a Dog as derived from Animal, you need to provide a reference to an actual CanFly and CantFly, respectively, to the constructor of their base Animal. Moreover, there is nothing that qualifies an Animal other than whether it can fly or not, so why have this class Animal (in addition to Fly)?
change your fly.cpp to fly.h, in Animal.cpp you should #include<fly.h> Or just define your myFly as a pointer Fly* myFly.
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.
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.