473,493 Members | 3,174 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

a problem with poliporphism

Hello. I'll try to explain my problem with an example:

I have the following classes:

class A {
public:
string name;
....
};

class B : public A
{
B(int x) {b=x; name="I am B"; }
int b;
getB() { return b };
};

class C : public A
{
C(int x) {c=x; name="I am C"; }
int c;
getC() { return c; }
};

Now, I need a vector<A*> v;

An there is a function like the following:

void p()
{
...
if(v[i]->name=="I am B"){ v[i]->getB() ...};
...
if(v[j]->name=="I am C") { v[j]->getC() ... };
...
};

It doesn't work because v contains objects of class A, but A doesn't
implement getB() nor getC().
But I need to have in the same vector objets of A, B and C. And I don't want
to declare getB and getC as virtual in A, because these methods will only be
defined in classes B and C respectively.

How can I do that?

Thanks.


Jul 22 '05 #1
25 1682
Some corrections:
I have the following classes:

class A {
public:
string name;
...
};

class B : public A
{
int b; public:
B(int x) {b=x; name="I am B"; } getB() { return b };
};

class C : public A
{
int c; public:
C(int x) {c=x; name="I am C"; }
getC() { return c; } };

Now, I need a vector<A*> v;

An there is a function like the following:

void p()
{
...
if(v[i]->name=="I am B"){ v[i]->getB() ...};
...
if(v[j]->name=="I am C") { v[j]->getC() ... };
...
};

It doesn't work because v contains objects of class A, but A doesn't
implement getB() nor getC().
But I need to have in the same vector objets of A, B and C. And I don't
want to declare getB and getC as virtual in A, because these methods will
only be defined in classes B and C respectively.

How can I do that?

Thanks.



Jul 22 '05 #2
Nafai wrote:
Some corrections:
More corrections

I have the following classes:

#include <string>
using std::string;
class A {
public:
string name;
...
};

class B : public A
{
int b;
public:
B(int x) {b=x; name="I am B"; }
getB() { return b };
int getB() { return b };
};

class C : public A
{
int c;


public:
C(int x) {c=x; name="I am C"; }
getC() { return c; }


int getC() { return c; }
};

Now, I need a vector<A*> v;

An there is a function like the following:

void p()
{
...
if(v[i]->name=="I am B"){ v[i]->getB() ...};
...
if(v[j]->name=="I am C") { v[j]->getC() ... };
...
};

It doesn't work because v contains objects of class A,
Actually, v contains _pointers_ to objects of class A. It would be
a disaster if v contained _objects_.
but A doesn't
implement getB() nor getC().
But I need to have in the same vector objets of A, B and C. And I don't
want to declare getB and getC as virtual in A, because these methods will
only be defined in classes B and C respectively.

How can I do that?


Declare

virtual int getValue() = 0;

in A and make B and C implement it by calling getB and getC respectively.

V
Jul 22 '05 #3

Declare

virtual int getValue() = 0;

in A and make B and C implement it by calling getB and getC respectively.

V


what about if C is like this (A and B are like before):

class C {
int c1, c2;
public:
int getC1() { return c1; }
int getC2() { return c2; }
};

vector<A*> v;
void p()
{
....
v[i]->getC1();
...
v[i]->getC2();
...
}

And another question:

list<A*> l;
A* p = new C(...);
l.push_front(p);
l.pop_front();

is *p destroyed?

Or even more: will list<A*>'s destructor destroy all the elements of l ?


Jul 22 '05 #4
Alexandros wrote:
Declare

virtual int getValue() = 0;

in A and make B and C implement it by calling getB and getC respectively.

V

what about if C is like this (A and B are like before):

class C {
int c1, c2;
public:
int getC1() { return c1; }
int getC2() { return c2; }
};

vector<A*> v;
void p()
{
....
v[i]->getC1();
...
v[i]->getC2();
...
}


Not going to work. If C and B are so different, they have no business to
reside in the same container to begin with. The only reason for B and C
to have a base class is if they have something _in common_. If they have
_nothing_ in common, what polymorphism can we talk about here?

Of course, you could try to claim that they have the _name_ in common, but
come on, what polymorphism is there if the only thing they share is the
ability to have a name? If that's so, the only thing you can do with them
polymorphically is to learn the names of the objects.
And another question:

list<A*> l;
A* p = new C(...);
l.push_front(p);
l.pop_front();

is *p destroyed?
No.
Or even more: will list<A*>'s destructor destroy all the elements of l ?


No, it will not. It has to be done manually (since it was allocated
without 'list's involvement, the list has no business trying to free
them.

V
Jul 22 '05 #5

Not going to work. If C and B are so different, they have no business to
reside in the same container to begin with. The only reason for B and C
to have a base class is if they have something _in common_. If they have
_nothing_ in common, what polymorphism can we talk about here?

Of course, you could try to claim that they have the _name_ in common, but
come on, what polymorphism is there if the only thing they share is the
ability to have a name? If that's so, the only thing you can do with
them polymorphically is to learn the names of the objects.


That was only an example; classes A,B and C have many things in common.
Actually their only difference is what I show in that example.

Jul 22 '05 #6
Nafai wrote:
Not going to work. If C and B are so different, they have no business to
reside in the same container to begin with. The only reason for B and C
to have a base class is if they have something _in common_. If they have
_nothing_ in common, what polymorphism can we talk about here?

Of course, you could try to claim that they have the _name_ in common,
but
come on, what polymorphism is there if the only thing they share is the
ability to have a name? If that's so, the only thing you can do with
them polymorphically is to learn the names of the objects.

That was only an example; classes A,B and C have many things in common.
Actually their only difference is what I show in that example.


Well, then it's not fair to talk about them out of context...

The whole idea of using containers with polymorphic types is that the
objects (through pointers) are used polymorphically. As soon as you have
to figure out the "real" types of objects via some kind of RTTI (your 'if
name is "I am B" ' _is_ RTTI, in essence), you step away from polymorphic
behaviour.

Yes, you can always do

if (v[i]->is_really_of_type_B()) { // whatever 'is_really_of_type_B' is
B* pb = dynamic_cast<B*>(v[i]);
// use pb however you want
}
else if (v[i]->is_really_of_type_C()) { // same here
C* pc = dynamic_cast<C*>(v[i]);

... et cetera ...

Hell, you can write

if (B* pb = dynamic_cast<B*>(v[i])) {
// use pb
}
else if (C* pc = dynamic_cast<C*>(v[i])) {
// use pc
}

and so on. But both approaches _require_ that you know what types derive
from 'A' _ahead_of_time_, while writing that code. What if I come later
and derive another type from A and want to store it in the same container?
SOL? Or do I have to come in and edit that function and every piece of
code that does that?

While it is possible to circumvent polymorphism in C++, you should
definitely think twice before writing code like that. Write some kind of
special processing code in the base class and make every derived class
override that thus providing _polymorphic_ processing.

You either put effort initially to _keep_ polymorphism, to adhere to OOD
principles, or you don't, then somebody else or maybe you will have to
put some effort _later_ to keep the system working.

V
Jul 22 '05 #7

"Nafai" <na*******@yahoo.es> wrote in message
news:rK*******************@telenews.teleline.es...
Hello. I'll try to explain my problem with an example:

I have the following classes:

class A {
public:
string name;
...
};

class B : public A
{
B(int x) {b=x; name="I am B"; }
int b;
getB() { return b };
};

class C : public A
{
C(int x) {c=x; name="I am C"; }
int c;
getC() { return c; }
};

Now, I need a vector<A*> v;

An there is a function like the following:

void p()
{
...
if(v[i]->name=="I am B"){ v[i]->getB() ...};
...
if(v[j]->name=="I am C") { v[j]->getC() ... };
...
};

It doesn't work because v contains objects of class A, but A doesn't
implement getB() nor getC().
But I need to have in the same vector objets of A, B and C. And I don't want
to declare getB and getC as virtual in A, because these methods will only be
defined in classes B and C respectively.

How can I do that?


You would come up with some other function name that makes sense in the general
case for all subtypes. What does it do? It just returns a value, that both B
and C seem to share. You haven't given enough information, but right off the
top if my head, I'd say take out "int c" and "int b" and put "int value" in A
instead. Then write a function "getValue" for A, and take out getB and getC.
Then you can write your code as such:

void p()
{
v[i]->getValue();
}
*That* is the point of polymorphism. No "ifs" for the type.
Jul 22 '05 #8

"Nafai" <em***@company.com> wrote in message
news:rE*******************@telenews.teleline.es...

Not going to work. If C and B are so different, they have no business to reside in the same container to begin with. The only reason for B and C
to have a base class is if they have something _in common_. If they have _nothing_ in common, what polymorphism can we talk about here?

Of course, you could try to claim that they have the _name_ in common, but come on, what polymorphism is there if the only thing they share is the
ability to have a name? If that's so, the only thing you can do with
them polymorphically is to learn the names of the objects.


That was only an example; classes A,B and C have many things in common.
Actually their only difference is what I show in that example.


There are several ways of doing this:
This way you can sort of downcast without using dynamic_cast, and you know
which classes you allow to cast to in class A. (this is what is done in the
composite pattern)

class C;
class B;

class A {
public:
virtual C* GetC() { return 0; };
virtual B* GetB(){ return 0; };
};

class B : public A{
public:
virtual B* GetB(){ return this; };
};

class C : public A{
public:
virtual C* GetC(){ return this; };
}

or you can implement methods that do nothing on the base class, and has
functionality on some of the derived...
(this is done in state pattern)

class A {
public:
virtual void doStuffB{};
virtual void doStuffC{};
};

class B: public A {
int x_;
public:
virtual void doStuffB{ x_ = 10; };
};

class C: public A {
int y_;
public:
virtual void doStuffC{ y_ = 10;};
};

You can probably solve this in more ways, but what ever way you choose to
solve it, the cleanest one would be to keep the interface between the base
class and its derivee's 100%. You might be able to use use template method
if you want something extra to happen in a derived class.. If you have a
need to add a function, that has nothing to do with the rest of the
hierachy, then take a look at the hierachy again, you might need to refactor
it..

Jul 22 '05 #9
Nafai wrote:

[snip]

What is poliporphism?
Jul 22 '05 #10
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote...
Nafai wrote:

[snip]

What is poliporphism?


Pinch your nose and try saying "polyMorphism". Whaddya get?
Jul 22 '05 #11
In Smalltalk I've seen somethings which in C++ would be like the following:

void aClass::aMethod()
{
throw("This class should not implement this method");
}
"Jesper Madsen" <ba***@mail.stofanet.dk> escribió en el mensaje
news:41***********************@nntp05.dk.telia.net ...

"Nafai" <em***@company.com> wrote in message
news:rE*******************@telenews.teleline.es...
>
> Not going to work. If C and B are so different, they have no business to > reside in the same container to begin with. The only reason for B and
> C
> to have a base class is if they have something _in common_. If they have > _nothing_ in common, what polymorphism can we talk about here?
>
> Of course, you could try to claim that they have the _name_ in common, but > come on, what polymorphism is there if the only thing they share is the
> ability to have a name? If that's so, the only thing you can do with
> them polymorphically is to learn the names of the objects.


That was only an example; classes A,B and C have many things in common.
Actually their only difference is what I show in that example.


There are several ways of doing this:
This way you can sort of downcast without using dynamic_cast, and you know
which classes you allow to cast to in class A. (this is what is done in
the
composite pattern)

class C;
class B;

class A {
public:
virtual C* GetC() { return 0; };
virtual B* GetB(){ return 0; };
};

class B : public A{
public:
virtual B* GetB(){ return this; };
};

class C : public A{
public:
virtual C* GetC(){ return this; };
}

or you can implement methods that do nothing on the base class, and has
functionality on some of the derived...
(this is done in state pattern)

class A {
public:
virtual void doStuffB{};
virtual void doStuffC{};
};

class B: public A {
int x_;
public:
virtual void doStuffB{ x_ = 10; };
};

class C: public A {
int y_;
public:
virtual void doStuffC{ y_ = 10;};
};

You can probably solve this in more ways, but what ever way you choose to
solve it, the cleanest one would be to keep the interface between the base
class and its derivee's 100%. You might be able to use use template method
if you want something extra to happen in a derived class.. If you have a
need to add a function, that has nothing to do with the rest of the
hierachy, then take a look at the hierachy again, you might need to
refactor
it..

Jul 22 '05 #12
With this example I want to show a problem when using polymorphism. The
classes A, B and C are supposed to have many things in common. I use "..."
to avoid writing them. I only focus on this difference between them (name
that methods "doSomethingWithCThatCannotBeDoneWithANorB()" instead of
"getC()") and the problem it means when using a polymorphic container.

"jeffc" <no****@nowhere.com> escribió en el mensaje
news:41********@news1.prserv.net...

"Nafai" <na*******@yahoo.es> wrote in message
news:rK*******************@telenews.teleline.es...
Hello. I'll try to explain my problem with an example:

I have the following classes:

class A {
public:
string name;
...
};

class B : public A
{
B(int x) {b=x; name="I am B"; }
int b;
getB() { return b };
};

class C : public A
{
C(int x) {c=x; name="I am C"; }
int c;
getC() { return c; }
};

Now, I need a vector<A*> v;

An there is a function like the following:

void p()
{
...
if(v[i]->name=="I am B"){ v[i]->getB() ...};
...
if(v[j]->name=="I am C") { v[j]->getC() ... };
...
};

It doesn't work because v contains objects of class A, but A doesn't
implement getB() nor getC().
But I need to have in the same vector objets of A, B and C. And I don't
want
to declare getB and getC as virtual in A, because these methods will only
be
defined in classes B and C respectively.

How can I do that?


You would come up with some other function name that makes sense in the
general
case for all subtypes. What does it do? It just returns a value, that
both B
and C seem to share. You haven't given enough information, but right off
the
top if my head, I'd say take out "int c" and "int b" and put "int value"
in A
instead. Then write a function "getValue" for A, and take out getB and
getC.
Then you can write your code as such:

void p()
{
v[i]->getValue();
}
*That* is the point of polymorphism. No "ifs" for the type.

Jul 22 '05 #13
Nafai wrote:
With this example I want to show a problem when using polymorphism.
The classes A, B and C are supposed to have many things in common. I
use "..." to avoid writing them. I only focus on this difference
between them (name that methods
"doSomethingWithCThatCannotBeDoneWithANorB()" instead of "getC()")
and the problem it means when using a polymorphic container.
Plain and simple it's a bad design from an object oriented viewpoint. You've
lost encapsulation and cohesion, and are introducing unneeded coupling. Your
fighting the C++ type system rather than working with it.

I see this kind of difficult to maintain code daily in a project that was a
'C' programmer's first attempt at C++. Usually, I'll find that the behavior
that's externalized in p() below is repeated numerous places throughout the
project. So the first step is to appropriately encapsulate the behavior. See
the comments/modifications below:
"jeffc" <no****@nowhere.com> escribió en el mensaje
news:41********@news1.prserv.net...

"Nafai" <na*******@yahoo.es> wrote in message
news:rK*******************@telenews.teleline.es...
Hello. I'll try to explain my problem with an example:

I have the following classes:

class A {
public:
string name;
This exposed data member is the first sign of something amiss. If it's not
used for any other purpose than type determination that you show below, you
can get rid of it. Otherwise make it private, or atleast protected.
...
Glossing over the most important aspects of this class is the second
indication of problems. Your code below shows derived classes and a
container of base class pointers. You should in that case indicate that this
class is intended to be used in that fashion with:

virtual ~A(){}

Now you should internalize the behavior of 'void p()' with:

virtual void p();

Not knowing what all your '...'s are doing you may need to have this virtual
member function take one or more arguments providing any necessary context.
Also this could be a pure virtual function (where derived classes must
define this method).

In some cases you may want to separate p()'s behavior into several virtual
member functions and make p() a non-virtual member function applying the
template pattern. Then p() would do the common operations calling the
virtual functions at the appropriate stages.

};

class B : public A
{
int b;
public:
B(int x):A("I am B"),b(x){}
virtual void p(){ /* do B's thing here */ }
};

class C : public A
{ int c;
public:
C(int x):A("I am C"),c(x){}
virtual void p(){ /* do C's thing here */ }
};

Now, I need a vector<A*> v;

An there is a function like the following:

void p()
{
...
typedef vector<A*> tPtrs;

for( tPtrs::iterator lItr = v.begin() ; lItr != v.end() ; ++lItr )
{
(*lItr)->p();
}
...
};

Jul 22 '05 #14
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?


Jul 22 '05 #15
KPB
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



Jul 22 '05 #16
"KPB" <k@w.net> escribió en el mensaje
news:vN*******************@fe10.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?
Jul 22 '05 #17
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; }
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?
}

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
Jul 22 '05 #18
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?
Jul 22 '05 #19
KPB
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
Jul 22 '05 #20
KPB escribió:
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.
Jul 22 '05 #21
Nafai wrote:
KPB escribió:
Nafai wrote:
KPB escribió:
Nafai wrote:

....
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
Jul 22 '05 #22

"Jonathan Mcdougall" <jo***************@DELyahoo.ca> escribió en el mensaje
news:UO****************@weber.videotron.net...
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; }


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?
}

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

That's OK, but I can't do that. If I could of course I would have. The
"process()" is done by another class. That is: I DO NEED to take "area",
"person" etc with where(), who() etc. There's no way to change this.
Jul 22 '05 #23
Nafai wrote:

That's OK, but I can't do that. If I could of course I would have. The
"process()" is done by another class. That is: I DO NEED to take "area",
"person" etc with where(), who() etc. There's no way to change this.


If you can't have virtual functions, you need to
emulate them either by using an id-switch (as you
did) or a type switch with dynamic_cast.

void f(Event *event)
{
if ( Emergency *e =
dynamic_cast<Emergency*>(event) )
{
}
else if ( Crime *c =
dynamic_cast<Crime*>(event) )
{
}
}

But that means f() must know about all the
subtypes and must test from down to top of the
hierarchy. That's a pain and it's ugly, but you
may have no choice.
Jonathan
Jul 22 '05 #24
Victor Bazarov wrote:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote...
Nafai wrote:

[snip]

What is poliporphism?

Pinch your nose and try saying "polyMorphism". Whaddya get?

For me, alas, a fart. :-)
Seriously, it's a cross between a parrot widget and a dolphin thingy.

--

Cheers
--
Hewson::Mike
"This letter is longer than usual because I lack the time to make it
shorter" - Blaise Pascal
Jul 22 '05 #25

"Nafai" <na*******@yahoo.es> wrote in message
news:D8*********************@telenews.teleline.es. ..
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

That's OK, but I can't do that. If I could of course I would have. The
"process()" is done by another class. That is: I DO NEED to take "area",
"person" etc with where(), who() etc. There's no way to change this.

How about passing a pointer to the instance of the class that will handle
the process() call? Or, perhaps better, make the pointer a member of the
Event class, and initialize it when creating the Event objects? Like
this...
// forward declared, so pointer can be used here
class ProcessClass;

class Event
{
ProcessClass* pProcessor;

public:
Event( ProcessClass* theProcessor ) : pProcessor(theProcessor);

virtual ~Event();

virtual void process() = 0; // that's the
// interface
};

class Emergency : public Event
{
public:
virtual void process() // that's a behavior
{
pProcessor->call_ambulance(where(),when());
}
};

class Crime : public Event
{
public:
virtual void process()
{
pProcessor->blame(who(),whatHeDid(),when()); // 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()
}
}

I haven't compiled this, just modified what Jonathon wrote, and I haven't
added back in the functions who(), where(), etc., but you can do that
yourself. Does this concept make sense now?

-Howard

Jul 22 '05 #26

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

Similar topics

1
8526
by: Richard Galli | last post by:
I want viewers to compare state laws on a single subject. Imagine a three-column table with a drop-down box on the top. A viewer selects a state from the list, and that state's text fills the...
0
3051
by: FreeStyle | last post by:
Hi everybody, I'm using phpMyAdmin 2.2.6 with EasyPHP v.1.6.0.0 I wrote a php script which uses a username (added in the mysql base with phpMyAdmin). This user has no privileges. But in the...
3
6558
by: Marcus | last post by:
I'm really confused with something I never had any problems with before... I have a form with a textbox called password. On the second page that $password is posted to, if I test isset($password)...
2
4232
by: fartsniff | last post by:
hello all, here is a preg_match routine that i am using. basically, $image is set in some code above, and it can be either st-1.gif or sb-1.gif (actually it randomly picks them from about 100...
2
8408
by: Fredrik Jonson | last post by:
Hello, I'm writing a newsletter poster for a website. I have some html news items which I want to turn into plain text and prettify before emailing it. Now, i have found wordwrap and...
0
2184
by: Aldo Polli | last post by:
Hi, I have this error when I start apache2 with php4 Syntax error on line 233 of /mypath/apache2/conf/httpd.conf: Cannot load /mypath/apache2/modules/libphp4.so into server: dynamic linker:...
2
6073
by: Marcus | last post by:
I am having some problems with trying to perform calculations on time fields. Say I have a start time and an end time, 1:00:00 and 2:30:00 (on a 24 hour scale, not 12). I want to find the...
1
3398
by: phpkid | last post by:
Howdy I've been given conflicting answers about search engines picking up urls like: http://mysite.com/index.php?var1=1&var2=2&var3=3 Do search engines pick up these urls? I've been considering...
1
5770
by: Randell D. | last post by:
Folks, I have a string that *could* contain any character - I want it to call a function that will allow me to pass the variable, and then return it cleaned of anything except alphanumeric,...
0
7119
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
7195
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...
0
7367
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5453
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4889
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3088
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3078
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
644
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
285
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.