 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Nafai Guest
|
Posted: Thu Dec 30, 2004 11:21 am Post subject: Re: a problem with poliporphism |
|
|
I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
}
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when()); break;
...
}
}
int main() {
list<Event*> lst;
.... // insert somehow Events in lst
Event* pEvt = lst.first();
lst.pop_first();
doSomethingWithEvent(pEvt);
....
}
My question is: which is the best way to do that? Is it OK like before?
|
|
| Back to top |
|
 |
KPB Guest
|
Posted: Thu Dec 30, 2004 12:42 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
}
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when()); break;
...
}
}
int main() {
list<Event*> lst;
.... // insert somehow Events in lst
Event* pEvt = lst.first();
lst.pop_first();
doSomethingWithEvent(pEvt);
....
}
My question is: which is the best way to do that? Is it OK like before?
|
In case it's not an oversight on your part, I just want to point out
that you should add a virtual destructor to your Event class. Even if
it's an empty *noop* you should still add it.
KPB
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Thu Dec 30, 2004 1:11 pm Post subject: Re: a problem with poliporphism |
|
|
"KPB" <k@w.net> escribió en el mensaje
news:vNSAd.25773$EH1.11348 (AT) fe10 (DOT) lga...
| Quote: | Nafai wrote:
I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
}
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when());
break;
...
}
}
int main() {
list<Event*> lst;
.... // insert somehow Events in lst
Event* pEvt = lst.first();
lst.pop_first();
doSomethingWithEvent(pEvt);
....
}
My question is: which is the best way to do that? Is it OK like before?
In case it's not an oversight on your part, I just want to point out that
you should add a virtual destructor to your Event class. Even if it's an
empty *noop* you should still add it.
KPB
|
OK.
But do you think that is a good desing? How could it be done better?
|
|
| Back to top |
|
 |
KPB Guest
|
Posted: Thu Dec 30, 2004 1:32 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | "KPB" <k@w.net> escribió en el mensaje
news:vNSAd.25773$EH1.11348 (AT) fe10 (DOT) lga...
Nafai wrote:
I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
}
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when());
break;
...
}
}
int main() {
list<Event*> lst;
.... // insert somehow Events in lst
Event* pEvt = lst.first();
lst.pop_first();
doSomethingWithEvent(pEvt);
....
}
My question is: which is the best way to do that? Is it OK like before?
In case it's not an oversight on your part, I just want to point out that
you should add a virtual destructor to your Event class. Even if it's an
empty *noop* you should still add it.
KPB
OK.
But do you think that is a good desing? How could it be done better?
|
Now that I look at it more, it's flawed in a few areas.
First of all, like I stated before, you *MUST* add a virtual destructor
to Event. If this was a simple oversight on your part, fine. However, if
you don't understand why this needs to be so, you need to research the
topic further. The FAQ is a good place to start.
Secondly, your voidDoSomethingWithEvents() is flawed. I'm guessing that
you didn't bother to try and compile this stuff because this function is
full of compilations errors.
This line for example:
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
pE is defined as Event* yet is calling "who()". Well, "who" is defined
in Crime so right here you're going to get a compilation error.
You either have to write a "who" implementation in Event or upcast (or
is it downcast?... I forget) this pointer to a pointer to Crime (which I
don't suggest here).
Try to get this function to compile. You'll see what I mean.
I think you need to research your materials (again the FAQ is a good
start) on inheritance.
KPB
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Thu Dec 30, 2004 1:38 pm Post subject: Re: a problem with poliporphism |
|
|
"KPB" <k@w.net> escribió en el mensaje
news:SvTAd.25776$a52.22950 (AT) fe10 (DOT) lga...
| Quote: | Nafai wrote:
"KPB" <k@w.net> escribió en el mensaje
news:vNSAd.25773$EH1.11348 (AT) fe10 (DOT) lga...
Nafai wrote:
I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
}
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime:
blame(pE->who(),pE->whatHeDid(),pE->when()); break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when());
break;
...
}
}
int main() {
list<Event*> lst;
.... // insert somehow Events in lst
Event* pEvt = lst.first();
lst.pop_first();
doSomethingWithEvent(pEvt);
....
}
My question is: which is the best way to do that? Is it OK like before?
In case it's not an oversight on your part, I just want to point out that
you should add a virtual destructor to your Event class. Even if it's an
empty *noop* you should still add it.
KPB
OK.
But do you think that is a good desing? How could it be done better?
Now that I look at it more, it's flawed in a few areas.
First of all, like I stated before, you *MUST* add a virtual destructor to
Event. If this was a simple oversight on your part, fine. However, if you
don't understand why this needs to be so, you need to research the topic
further. The FAQ is a good place to start.
Secondly, your voidDoSomethingWithEvents() is flawed. I'm guessing that
you didn't bother to try and compile this stuff because this function is
full of compilations errors.
This line for example:
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
pE is defined as Event* yet is calling "who()". Well, "who" is defined in
Crime so right here you're going to get a compilation error.
You either have to write a "who" implementation in Event or upcast (or is
it downcast?... I forget) this pointer to a pointer to Crime (which I
don't suggest here).
Try to get this function to compile. You'll see what I mean.
I think you need to research your materials (again the FAQ is a good
start) on inheritance.
KPB
Of course I didn't try to compile this. |
One solution for this to work is to add as virtual functions who(), where()
etc. in Event. But is that a GOOD SOLUTION?
|
|
| Back to top |
|
 |
KPB Guest
|
Posted: Thu Dec 30, 2004 1:45 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | Of course I didn't try to compile this.
|
Why not? You would've seen that your function doesn't compile. When
something doesn't compile, that's not GOOD DESIGN, right?
| Quote: | One solution for this to work is to add as virtual functions who(), where()
etc. in Event. But is that a GOOD SOLUTION?
|
That would be a good start since a pointer to your base class is calling
these functions.
KPB
|
|
| Back to top |
|
 |
KPB Guest
|
Posted: Thu Dec 30, 2004 1:49 pm Post subject: Re: a problem with poliporphism |
|
|
KPB wrote:
| Quote: | Nafai wrote:
Of course I didn't try to compile this.
Why not? You would've seen that your function doesn't compile. When
something doesn't compile, that's not GOOD DESIGN, right?
One solution for this to work is to add as virtual functions who(),
where() etc. in Event. But is that a GOOD SOLUTION?
That would be a good start since a pointer to your base class is calling
these functions.
KPB
|
One more thing. You state that a Crime and an Emergency is an event.
Ok... that makes good sense from a ISA point of view.
But think about this further: Is a Crime an Emergency? Perhaps your
hierarchy can be Event --> Emergency --> Crime? I don't know. I'm just
trying to get you to think about the DESIGN better.
KPB
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Thu Dec 30, 2004 1:56 pm Post subject: Re: a problem with poliporphism |
|
|
Let's focus on this function:
| Quote: | void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when());
break;
...
}
}
|
Do you think it is a good a idea to do this:
void doSomethingWithEvents(Event* pE)
{
Emergency* pEmergency;
switch(pE->kind) {
case Event::Emergency :
pEmergency=dynamic_cast<Emergency*>(pE);
callAmbulance(pEmergency->where(), pEmergency->when()); break;
... // and so on
}
}
|
|
| Back to top |
|
 |
KPB Guest
|
Posted: Thu Dec 30, 2004 2:03 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | Do you think it is a good a idea to do this:
void doSomethingWithEvents(Event* pE)
{
Emergency* pEmergency;
switch(pE->kind) {
case Event::Emergency :
pEmergency=dynamic_cast<Emergency*>(pE);
callAmbulance(pEmergency->where(), pEmergency->when()); break;
... // and so on
}
}
|
No. That leads me to another point on your classes. What's the point in
having polimorphism if the specific kind of event is stored as some
internal value of the Event class? Every time you add a new class, you
have to update your Event class to deal with a new "kind" enumeration.
So, with your current design, when you derive a class from Event, you
also have to modify the Event class. Not good design.
Ditch the enum list in Event.
KPB
|
|
| Back to top |
|
 |
Jeff Flinn Guest
|
Posted: Thu Dec 30, 2004 2:14 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
}
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency :
callAmbulance(pE->where(),pE->when()); break;
case Event::Crime:
blame(pE->who(),pE->whatHeDid(),pE->when()); break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when());
break; ...
}
}
int main() {
list<Event*> lst;
... // insert somehow Events in lst
Event* pEvt = lst.first();
lst.pop_first();
doSomethingWithEvent(pEvt);
...
}
My question is: which is the best way to do that? Is it OK like
before?
|
It's not 'OK' as it was not 'OK' before.
All of my previous comments apply. The only difference I see here is you've
renamed 'p' to doSomethingWithEvents. What was wrong with the approach I
previously suggested?
I can not do your job for you. I can only suggest that you do some reading,
such as "Design Patterns" by GoF, and "Accelerated C++" by K & M.
Jeff
|
|
| Back to top |
|
 |
Jonathan Mcdougall Guest
|
Posted: Thu Dec 30, 2004 4:45 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | I am going to give a more detailed example:
// I don't type the constructors.
class Event {
private:
int time;
EventType kind;
public:
enum EventType { Event1, Event2,...,Emergency,Crime};
int when() {return time; }
EventType what() { return kind; }
|
Event is meant to be used as a base class and does
not have a virtual destructor nor virtual
functions. What kind of base class is that?
| Quote: | }
class Emergency : public Event {
private:
int area;
public:
int where() {return area;}
};
class Crime : public Event {
private:
string person;
int aCrime;.
public:
string who() { return person; }
int whatHeDid() { return aCrime; }
};
void doSomethingWithEvents(Event* pE)
{
switch(pE->kind) {
case Event::Emergency : callAmbulance(pE->where(),pE->when());
break;
case Event::Crime: blame(pE->who(),pE->whatHeDid(),pE->when());
break;
case Event::Event1 : doSomethingRelatedToEvent1(pE->when()); break;
...
}
}
|
That is not recommended. You seem not to
understand the use of polymorphism and public
inheritance.
Public inheritance has many uses, but in your
case, it is a simple case of interface<->behavior.
The base class specifies an interface (with
[pure] virtual functions) and derived classes
specify the behavior.
class Event
{
public:
virtual ~Event();
virtual void process() = 0; // that's the
// interface
};
class Emergency : public Event
{
private:
void call_ambulance();
public:
virtual void process() // that's a behavior
{
call_ambulance();
}
};
class Crime : public Event
{
private:
void blame();
public:
virtual void process()
{
blame(); // that's another behavior
}
};
typedef std::sector<Event*> Events;
void f(Events &events)
{
for (Events::iterator itor=events.begin();
itor!=events.end();
++itor)
{
Event *e = *itor;
e->process(); // calls the correct
// process()
}
}
Jonathan
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Thu Dec 30, 2004 8:00 pm Post subject: Re: a problem with poliporphism |
|
|
KPB escribió:
| Quote: | Nafai wrote:
Do you think it is a good a idea to do this:
void doSomethingWithEvents(Event* pE)
{
Emergency* pEmergency;
switch(pE->kind) {
case Event::Emergency :
pEmergency=dynamic_cast<Emergency*>(pE);
callAmbulance(pEmergency->where(), pEmergency->when());
break;
... // and so on
}
}
No. That leads me to another point on your classes. What's the point in
having polimorphism if the specific kind of event is stored as some
internal value of the Event class? Every time you add a new class, you
have to update your Event class to deal with a new "kind" enumeration.
So, with your current design, when you derive a class from Event, you
also have to modify the Event class. Not good design.
Ditch the enum list in Event.
KPB
|
OK. So what desing would be the best in your opinion? How would you
solve that problem?
|
|
| Back to top |
|
 |
KPB Guest
|
Posted: Thu Dec 30, 2004 8:08 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | KPB escribió:
Nafai wrote:
Do you think it is a good a idea to do this:
void doSomethingWithEvents(Event* pE)
{
Emergency* pEmergency;
switch(pE->kind) {
case Event::Emergency :
pEmergency=dynamic_cast<Emergency*>(pE);
callAmbulance(pEmergency->where(), pEmergency->when());
break;
... // and so on
}
}
No. That leads me to another point on your classes. What's the point
in having polimorphism if the specific kind of event is stored as some
internal value of the Event class? Every time you add a new class, you
have to update your Event class to deal with a new "kind" enumeration.
So, with your current design, when you derive a class from Event, you
also have to modify the Event class. Not good design.
Ditch the enum list in Event.
KPB
OK. So what desing would be the best in your opinion? How would you
solve that problem?
|
I've told you quite a bit about what I'd do.
I'm sorry but I think you need to study the topic of inheritence a
little better.
KPB
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Thu Dec 30, 2004 8:23 pm Post subject: Re: a problem with poliporphism |
|
|
KPB escribió:
| Quote: | Nafai wrote:
KPB escribió:
Nafai wrote:
Do you think it is a good a idea to do this:
void doSomethingWithEvents(Event* pE)
{
Emergency* pEmergency;
switch(pE->kind) {
case Event::Emergency :
pEmergency=dynamic_cast<Emergency*>(pE);
callAmbulance(pEmergency->where(), pEmergency->when());
break;
... // and so on
}
}
No. That leads me to another point on your classes. What's the point
in having polimorphism if the specific kind of event is stored as
some internal value of the Event class? Every time you add a new
class, you have to update your Event class to deal with a new "kind"
enumeration.
So, with your current design, when you derive a class from Event, you
also have to modify the Event class. Not good design.
Ditch the enum list in Event.
KPB
OK. So what desing would be the best in your opinion? How would you
solve that problem?
I've told you quite a bit about what I'd do.
I'm sorry but I think you need to study the topic of inheritence a
little better.
KPB
|
Just tell me an outline of your solution. I know what it is polymorphism
and what is inheritance. Please, just tell me your solution. If you have it.
|
|
| Back to top |
|
 |
Jeff Flinn Guest
|
Posted: Thu Dec 30, 2004 8:26 pm Post subject: Re: a problem with poliporphism |
|
|
Nafai wrote:
| Quote: | KPB escribió:
Nafai wrote:
KPB escribió:
Nafai wrote:
|
....
| Quote: | Just tell me an outline of your solution. I know what it is
polymorphism and what is inheritance. Please, just tell me your
solution. If you have it.
|
You've been told a few times by a few people already. Give it your best
shot, post your try here and you'll get some help.
Jeff
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|