473,386 Members | 1,830 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

A (Simple) Polymorphism Query

Hi Everyone,

Please take a look at the following (simple and fun) program:

////////////////////////////////////////////////////////////////////////////
/////////////
// Monster Munch, example program

#include <list>

class CFood
{
public:
CFood() {}
virtual ~CFood() {}
};

class CFoodCookie : public CFood
{
public:
CFoodCookie() {}
virtual ~CFoodCookie() {}
};

class CFoodHorse : public CFood
{
public:
CFoodHorse() {}
virtual ~CFoodHorse() {}
};

class CMonster
{
public:
CMonster() {}
~CMonster() {}

// The (greedy) monster may eat several things
void Eat(CFood* pSnack) {delete pSnack; printf("\nI ate summink, but I know
not what.");}
void Eat(CFoodCookie* pSnack) {delete pSnack; printf("\nYummy! A
cookie!");}
void Eat(CFoodHorse* pSnack) {delete pSnack; printf("\nI was so hungry I
ate a horse!");}
};

class CPantry
{
public:
CPantry() {}
~CPantry() {}

void AddFood(CFood* pFood)
{
// Add the food to our supplies
m_Stock.push_back(pFood);
}

void Feed(CMonster& Monster)
{
while (m_Stock.size())
{
// Get the food...
CFood* pFood = m_Stock.front();
m_Stock.pop_front();

// Feed the monster
Monster.Eat(pFood);
}
}

private:
std::list<CFood*> m_Stock;
};

int _tmain(int argc, _TCHAR* argv[])
{
CPantry ThePantry;

// Let's see what we have:
// Two cookies...
ThePantry.AddFood(new CFoodCookie());
ThePantry.AddFood(new CFoodCookie());
// Goodness knows what this is...
ThePantry.AddFood(new CFood());
// And this, apparently...
ThePantry.AddFood(new CFoodHorse());

// Feed the guest...
CMonster ScaryDude;
ThePantry.Feed(ScaryDude);

getchar();

return 0;
}
////////////////////////////////////////////////////////////////////

I may be overlooking a very simple trick indeed, but my question is this:
how do I have the monster know what he (or she, who knows?) is eating? There
are a couple of factors that I wish to preserve in the solution:
1. The monster must have the overloaded Eat members as I intend to implement
similar classes that will eat the same and different foods in different
manners (with manners, perhaps? :-) ).
2. The pantry must be the source of food and must store food in a generic
manner.
3. I want users to implement new CFood derived classes as simply as
possible.

I could, for example, have a virtual Feed(CMonster&) method in all CFood
derived classes that executes Monster.Eat(this). However, this would impact
factor 3 in that all new CFood-derived classes would need to add this
method - if implemented in the CFood base class only, the monster would only
eat generic food.

What would be your suggestions, folks? Is there a simple, or non-simple
polymorphic step I am missing? Would templates be an answer somewhere?

Many, many thanks!
Lucy x
Jul 19 '05 #1
3 3644
"Patchwork" <ID***********@IDontLike.Spam> wrote...
Please take a look at the following (simple and fun) program:

//////////////////////////////////////////////////////////////////////////// /////////////
// Monster Munch, example program

#include <list>

class CFood
{
public:
CFood() {}
virtual ~CFood() {}
};

class CFoodCookie : public CFood
{
public:
CFoodCookie() {}
virtual ~CFoodCookie() {}
};

class CFoodHorse : public CFood
{
public:
CFoodHorse() {}
virtual ~CFoodHorse() {}
};

class CMonster
{
public:
CMonster() {}
~CMonster() {}

// The (greedy) monster may eat several things
void Eat(CFood* pSnack) {delete pSnack; printf("\nI ate summink, but I know not what.");}
void Eat(CFoodCookie* pSnack) {delete pSnack; printf("\nYummy! A
cookie!");}
void Eat(CFoodHorse* pSnack) {delete pSnack; printf("\nI was so hungry I
ate a horse!");}
};

class CPantry
{
public:
CPantry() {}
~CPantry() {}

void AddFood(CFood* pFood)
{
// Add the food to our supplies
m_Stock.push_back(pFood);
}

void Feed(CMonster& Monster)
{
while (m_Stock.size())
{
// Get the food...
CFood* pFood = m_Stock.front();
m_Stock.pop_front();

// Feed the monster
Monster.Eat(pFood);
}
}

private:
std::list<CFood*> m_Stock;
};

int _tmain(int argc, _TCHAR* argv[])
This is not C++. In C++ the entry point should be called
'main' and have very particular parameters.
{
CPantry ThePantry;

// Let's see what we have:
// Two cookies...
ThePantry.AddFood(new CFoodCookie());
ThePantry.AddFood(new CFoodCookie());
// Goodness knows what this is...
ThePantry.AddFood(new CFood());
// And this, apparently...
ThePantry.AddFood(new CFoodHorse());

// Feed the guest...
CMonster ScaryDude;
ThePantry.Feed(ScaryDude);

getchar();

return 0;
}
////////////////////////////////////////////////////////////////////

I may be overlooking a very simple trick indeed, but my question is this:
how do I have the monster know what he (or she, who knows?) is eating?
Unless you somehow perform run-time type resolution (like dynamic_cast,
for example), and keep passing 'CFood*' to the overloaded member of
the CMonster class, CMonster::Eat(CFood*) _shall__always_ be chosen.

Now, there is a bigger problem here. Your CMonster will still _have_to_
know all the different foods there possibly can be in order to behave
correctly. That's no polymorphism.
There
are a couple of factors that I wish to preserve in the solution:
1. The monster must have the overloaded Eat members as I intend to implement similar classes that will eat the same and different foods in different
manners (with manners, perhaps? :-) ).
That means you will have to limit your monster to some _categories_ of
food, anyway. So, why don't you place that category table (or list, or
enumeration) into the CFood base class and let the monster behave
differently based on the category the food returns?
2. The pantry must be the source of food and must store food in a generic
manner.
3. I want users to implement new CFood derived classes as simply as
possible.

I could, for example, have a virtual Feed(CMonster&) method in all CFood
derived classes that executes Monster.Eat(this). However, this would impact factor 3 in that all new CFood-derived classes would need to add this
method - if implemented in the CFood base class only, the monster would only eat generic food.
In polymorphism, the only way to do it is to let CFood descendants
provide the distinguishing functionality. Otherwise, it's not the
polymorphism we know.
What would be your suggestions, folks? Is there a simple, or non-simple
polymorphic step I am missing? Would templates be an answer somewhere?


You're missing the whole point of polymorphism, I am afraid.

Victor
Jul 19 '05 #2
Hi Victor,

Thanks for your response...

----- Original Message -----
From: "Victor Bazarov" <v.********@comAcast.net>
Newsgroups: comp.lang.c++
Sent: Sunday, November 16, 2003 4:27 AM
Subject: Re: A (Simple) Polymorphism Query

"Patchwork" wrote...
Please take a look at the following (simple and fun) program:

////////////////////////////////////////////////////////////////////////////
/////////////
// Monster Munch, example program

#include <list>

class CFood
{
public:
CFood() {}
virtual ~CFood() {}
};

class CFoodCookie : public CFood
{
public:
CFoodCookie() {}
virtual ~CFoodCookie() {}
};

class CFoodHorse : public CFood
{
public:
CFoodHorse() {}
virtual ~CFoodHorse() {}
};

class CMonster
{
public:
CMonster() {}
~CMonster() {}

// The (greedy) monster may eat several things
void Eat(CFood* pSnack) {delete pSnack; printf("\nI ate summink, but I

know
not what.");}
void Eat(CFoodCookie* pSnack) {delete pSnack; printf("\nYummy! A
cookie!");}
void Eat(CFoodHorse* pSnack) {delete pSnack; printf("\nI was so hungry I ate a horse!");}
};

class CPantry
{
public:
CPantry() {}
~CPantry() {}

void AddFood(CFood* pFood)
{
// Add the food to our supplies
m_Stock.push_back(pFood);
}

void Feed(CMonster& Monster)
{
while (m_Stock.size())
{
// Get the food...
CFood* pFood = m_Stock.front();
m_Stock.pop_front();

// Feed the monster
Monster.Eat(pFood);
}
}

private:
std::list<CFood*> m_Stock;
};

int _tmain(int argc, _TCHAR* argv[])


This is not C++. In C++ the entry point should be called
'main' and have very particular parameters.


Point taken, I overlooked this added by my compiler in a dash to create the
demonstration program.
{
CPantry ThePantry;

// Let's see what we have:
// Two cookies...
ThePantry.AddFood(new CFoodCookie());
ThePantry.AddFood(new CFoodCookie());
// Goodness knows what this is...
ThePantry.AddFood(new CFood());
// And this, apparently...
ThePantry.AddFood(new CFoodHorse());

// Feed the guest...
CMonster ScaryDude;
ThePantry.Feed(ScaryDude);

getchar();

return 0;
}
////////////////////////////////////////////////////////////////////

I may be overlooking a very simple trick indeed, but my question is this: how do I have the monster know what he (or she, who knows?) is eating?


Unless you somehow perform run-time type resolution (like dynamic_cast,
for example), and keep passing 'CFood*' to the overloaded member of
the CMonster class, CMonster::Eat(CFood*) _shall__always_ be chosen.


Again, thanks for taking the time to look over the code. I do see that this
is my problem but I was hoping there would be a simple and convenient way to
pass the desired class type without implementing this in CFood-derived
classes.
Now, there is a bigger problem here. Your CMonster will still _have_to_
know all the different foods there possibly can be in order to behave
correctly. That's no polymorphism.
Hmm. Again, I see your point. My subject heading is the erroneous factor
here. I do desire that the monster behaves this way with a pre-determined
list of foods specifically handled. Polymorphic behaviour, in its true
sense, is expected of the CFood classes within the CPantry class and
elsewhere. Consequently, it is only the CMonster class that I wish to
implement in this novel manner by reacting differently to different foods.
The 'handler' for the generic food type is there to allow the monster to eat
any type of food indiscriminately if required.
There
are a couple of factors that I wish to preserve in the solution:
1. The monster must have the overloaded Eat members as I intend to

implement
similar classes that will eat the same and different foods in different
manners (with manners, perhaps? :-) ).


That means you will have to limit your monster to some _categories_ of
food, anyway. So, why don't you place that category table (or list, or
enumeration) into the CFood base class and let the monster behave
differently based on the category the food returns?


Indeed, the moster's CFood type handling isn't an overisight, as mentioned
above. The bigger picture is that we may have a CLifeform class with
subclasses that override handlers only for the foodtypes they are interested
in eating. Do you think categories via enumerated types, etc would be the
ideal solution? I was wanting to avoid implementing type checks/cases in the
CMonster class by having certain foods naturally handled in their
corresponding method overrides.
2. The pantry must be the source of food and must store food in a generic manner.
3. I want users to implement new CFood derived classes as simply as
possible.

I could, for example, have a virtual Feed(CMonster&) method in all CFood
derived classes that executes Monster.Eat(this). However, this would

impact
factor 3 in that all new CFood-derived classes would need to add this
method - if implemented in the CFood base class only, the monster would

only
eat generic food.


In polymorphism, the only way to do it is to let CFood descendants
provide the distinguishing functionality. Otherwise, it's not the
polymorphism we know.


Yes, again, I make no excuses for the mistitled e-mail but could you think
of any further tricks that may help me achieve what I hope for?
What would be your suggestions, folks? Is there a simple, or non-simple
polymorphic step I am missing? Would templates be an answer somewhere?


You're missing the whole point of polymorphism, I am afraid.


Well, let's say I suffered an aberrant thought when naming the message...:-)

Perhaps I will rethink my overall design (surely your recommendation? :-) )
but any further suggestions would be most appreciated. I don't really know
of any newsgroups that would be interested in discussing models, etc in C++
that would be interested in making some suggestions for another design. Any
help from anyone here in achieving what I desire would be _most_ appreciated
:-)

To reiterate the requirements:
1) There is a class type CFood which will have more subclasses added in the
future. Each foodtype will have its own properties, etc making good use of
polymorphism where appropriate (honest).
2) There is a class CPantry which will store a dynamic quantity of CFood
based classes. The specific CFood-derived class type need not be known.
3) There is a class CLifeform that will have subclasses such as CMonster or
CHumanoid. Each CLifeform-based class may process or eat CFood-based objects
differently. A default 'handler' may be desirable just to mention that the
lifeform is not interest in the food type.
4) Other classes (not CLifeform-drived) may also 'handle' CFood objects.

If the above model is not appropriate...what could be changed? Or what
could be used in its place?

Perhaps it is more appropriate to post this as a new question...?
Victor


Thanks, Victor
Lucy x
Jul 19 '05 #3
"Patchwork" <ID***********@IDontLike.Spam> wrote...
----- Original Message -----
From: "Victor Bazarov" <v.********@comAcast.net>
Newsgroups: comp.lang.c++
Sent: Sunday, November 16, 2003 4:27 AM
Subject: Re: A (Simple) Polymorphism Query

"Patchwork" wrote...
Please take a look at the following (simple and fun) program: [...]
Now, there is a bigger problem here. Your CMonster will still _have_to_
know all the different foods there possibly can be in order to behave
correctly. That's no polymorphism.
Hmm. Again, I see your point. My subject heading is the erroneous factor
here. I do desire that the monster behaves this way with a pre-determined
list of foods specifically handled. Polymorphic behaviour, in its true
sense, is expected of the CFood classes within the CPantry class and
elsewhere. Consequently, it is only the CMonster class that I wish to
implement in this novel manner by reacting differently to different foods.
The 'handler' for the generic food type is there to allow the monster to

eat any type of food indiscriminately if required.
There
are a couple of factors that I wish to preserve in the solution:
1. The monster must have the overloaded Eat members as I intend to implement
similar classes that will eat the same and different foods in different manners (with manners, perhaps? :-) ).


That means you will have to limit your monster to some _categories_ of
food, anyway. So, why don't you place that category table (or list, or
enumeration) into the CFood base class and let the monster behave
differently based on the category the food returns?


Indeed, the moster's CFood type handling isn't an overisight, as mentioned
above. The bigger picture is that we may have a CLifeform class with
subclasses that override handlers only for the foodtypes they are

interested in eating. Do you think categories via enumerated types, etc would be the
ideal solution? I was wanting to avoid implementing type checks/cases in the CMonster class by having certain foods naturally handled in their
corresponding method overrides.
Alright, given these new conditions, I don't think that enumerators
would be ideal. The _ideal_ would be to teach each life form to
recognise the food they can eat (based on some specific characteristics
of the food, like hallucinogen-ness) and store [a pointer to] a sample
in their "set of acceptable foods". The whole point of it is that you
(or your life forms) can never tell what foods they will encounter on
their path to oblivion, especially considering that foods and creatures
are not related types and can be created independently.

So, let's re-visit categories now. What you need to give your CFood
class is a way to express itself: soft, chunky, needs cooking, stinks,
liquid, fatty, etc., and also give your CLifeform a mechanism which
will calculate acceptability of a particular food based on its factors.
I imagine that it is possible that your monster would say "I don't know
what I just ate, but it tasted like horse".
[...]
Perhaps I will rethink my overall design (surely your recommendation? :-) ) but any further suggestions would be most appreciated. I don't really know
of any newsgroups that would be interested in discussing models, etc in C++ that would be interested in making some suggestions for another design. Any help from anyone here in achieving what I desire would be _most_ appreciated :-)
Two suggestions: James Coplien's "Advanced C++" (1991) and comp.object.

To reiterate the requirements:
1) There is a class type CFood which will have more subclasses added in the future. Each foodtype will have its own properties, etc making good use of
polymorphism where appropriate (honest).
Sounds good. Among the properties you could add a name, which will
be set by a first creature ever trying the food (unless the food has
already been stored in a box with a known name). Other creatures
can then ask the food what its name is and store the name (not some
'sample') in the set of foods it likes.
2) There is a class CPantry which will store a dynamic quantity of CFood
based classes. The specific CFood-derived class type need not be known.
Sure. Seems OK. Unless the food needs to be refridgirated to be
OK (or does your pantry have a fridge in it?)
3) There is a class CLifeform that will have subclasses such as CMonster or CHumanoid. Each CLifeform-based class may process or eat CFood-based objects differently. A default 'handler' may be desirable just to mention that the
lifeform is not interest in the food type.
Well, see above. I think that more sophisticated mechanism for the
life forms to distinguish between foods is needed.
4) Other classes (not CLifeform-drived) may also 'handle' CFood objects.

If the above model is not appropriate...what could be changed? Or what
could be used in its place?
It's appropriate. It's just too generic. You might want to begin
stating the details, for example, how would "other classes" "handle"
food? Spoil it? Heat it? A food's properties should probably
change based on that. Have you thought of what properties and how
are going to change?
Perhaps it is more appropriate to post this as a new question...?


Nah, just keep digging, I am fairly certain you're on the right track.

Good luck, and keep asking those questions!

Victor
Jul 19 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
by: Ken | last post by:
Hi. Can anyone refer me to any articles about the compatibility between c++ polymorphism and real-time programming? I'm currently on a real-time c++ project, and we're having a discussion...
11
by: richard pickworth | last post by:
Can anyone explain polymorphism?(very simply). thanks richard
12
by: Steve Jorgensen | last post by:
The classing Visual Basic and VBA support for polymorphism, let's face it, is a bit on the weak side, and built-in support for inheritance is non-existent. This little essay is about some patterns...
4
by: LP | last post by:
Hi, I understand the concept/definition of polymorphism. But what does the term "runtime polymorphism" mean? I was asked to define it during a technical interview. I gave a guy vanilla definition...
4
by: Mike | last post by:
It looks to me that in using that in creating generic IEnumerables, you lose polymorphic capabilities. Consider this pseudo code: abstract class BaseClass; class...
1
by: relient | last post by:
Hi, I just started the chapter on "Inheritance" and I'm a bit confused so I have three questions: first, here's the code: using System; using System.Collections.Generic; using System.Text; ...
2
by: sarathy | last post by:
Hi all, I need a small clarification reg. Templates and Polymorphism. I believe templates is really a good feature, which can be used to implement generic functions and classes. But i doubt...
11
by: chsalvia | last post by:
I've been programming in C++ for a little over 2 years, and I still find myself wondering when I should use polymorphism. Some people claim that polymorphism is such an integral part of C++,...
17
by: Bart Friederichs | last post by:
Hello, I created the following inheritance: class Parent { public: void foo(int i); }; class Child : public Parent {
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.