overloading a function

J

Joe

Hi,

Can I pass a "generic" class pointer as an argument to a function?


For instance say classA and B are both derived from Z.

{
int iType =1;

Class? * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;


OverloadedFunc(pGeneric);
}

Where

OverloadedFunc( ClassA *pA){}
OverloadedFunc( ClassA *pB){}

or must I do:

if(iType==0)
{ ClassA *pA= new ClassA;
OverloadedFunc(pB); }
else
{ ClassB *pB= new ClassB;
OverloadedFunc(pB); }

Thanks
 
J

John Harrison

Joe said:
Hi,

Can I pass a "generic" class pointer as an argument to a function?


For instance say classA and B are both derived from Z.

{
int iType =1;

Class? * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;


OverloadedFunc(pGeneric);
}

Where

OverloadedFunc( ClassA *pA){}
OverloadedFunc( ClassA *pB){}

or must I do:

if(iType==0)
{ ClassA *pA= new ClassA;
OverloadedFunc(pB); }
else
{ ClassB *pB= new ClassB;
OverloadedFunc(pB); }

Thanks

Why not use the base class?

void OverloadedFunc( ClassZ *pZ){}

That would be the usual thing to do.

john
 
J

John Harrison

John Harrison said:
Why not use the base class?

void OverloadedFunc( ClassZ *pZ){}

That would be the usual thing to do.

john

Alternatively (I think I see where you are going now) make OverloadedFunc a
virtual member function of ClassA, ClassB and ClassZ, then you can write

int iType =1;

ClassZ * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;

pGeneric->OverloadedFunc();

And if that isn't OK for some reason, use dynamic_cast.

int iType =1;

ClassZ * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;

ClassA * pA;
ClassB * pB;
if (pA = dynamic_cast<ClassA*>(pGeneric))
OverloadedFunc(pA);
else if (pB = dynamic_cast<ClassB*>(pGeneric))
OverloadedFunc(pB);
else
error;

john
 
J

Joe

Alternatively (I think I see where you are going now) make OverloadedFunc a
virtual member function of ClassA, ClassB and ClassZ, then you can write

int iType =1;

ClassZ * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;

pGeneric->OverloadedFunc();


That would be a bit messy I think as the overloaded function is part of
another class already.
And if that isn't OK for some reason, use dynamic_cast.

int iType =1;

ClassZ * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;

ClassA * pA;
ClassB * pB;
if (pA = dynamic_cast<ClassA*>(pGeneric))
OverloadedFunc(pA);
else if (pB = dynamic_cast<ClassB*>(pGeneric))
OverloadedFunc(pB);
else
error;

That doesn't look any cleaner than my original.
So it appears that you can't define a "generic" type of pointer which
"knows"
what class it points to, so that when passed as a parameter an overloaded
function can ID its type and call its correct version.
 
S

Sharad Kala

Alternatively (I think I see where you are going now) make OverloadedFunc a
virtual member function of ClassA, ClassB and ClassZ, then you can write

To OP - Then it should probably be called OverRiddenFunc and not
OverloadedFunc.
 
J

John Harrison

Joe said:
OverloadedFunc


That would be a bit messy I think as the overloaded function is part of
another class already.


That doesn't look any cleaner than my original.
So it appears that you can't define a "generic" type of pointer which
"knows"
what class it points to, so that when passed as a parameter an overloaded
function can ID its type and call its correct version.

You can, but only when that pointer is the object on which a virtual method
is called.

pGeneric->OverloadedFunc();

Here pGeneric can be declared as ClassZ* but the application knows when it
calls OverloadedFunc whether to class the ClassA version or the ClassB
version.

Since you say that OverloadedFunc is already a member of a different class
it seems that maybe what you are searching for is called 'double dispatch'.
That means making a method call virtual on two different pointers
simultaneously. It true that C++ doesn't support this directly but various
techniques have been tried, it does get messy though. Try googling if you're
interested.

john
 
T

tom_usenet

That doesn't look any cleaner than my original.
So it appears that you can't define a "generic" type of pointer which
"knows"
what class it points to, so that when passed as a parameter an overloaded
function can ID its type and call its correct version.

Not in a statically typed language, no! The solution is to use static
or dynamic polymorphism. The latter very much looks like the way to go
here, but you haven't stated what you're doing, so it's hard to tell.

Tom
 
T

tom_usenet

Hi,

Can I pass a "generic" class pointer as an argument to a function?


For instance say classA and B are both derived from Z.

{
int iType =1;

Class? * pGeneric;

if(iType==0)
pGeneric= new ClassA;
else
pGeneric= new ClassB;


OverloadedFunc(pGeneric);
}

Where

OverloadedFunc( ClassA *pA){}
OverloadedFunc( ClassA *pB){}

or must I do:

if(iType==0)
{ ClassA *pA= new ClassA;
OverloadedFunc(pB); }
else
{ ClassB *pB= new ClassB;
OverloadedFunc(pB); }

template <class T>
void doFunc()
{
T* pT = new T;
OverloadedFunc(pT);
}

Then:

if (iType == 0)
doFunc<ClassA>();
else
doFunc<ClassB>();

But it looks to me like you should be using virtual functions and a
common base class - type-switches are pretty much *always* indicative
of a problematic design.

Tom
 
J

Joe

tom_usenet said:
Not in a statically typed language, no! The solution is to use static
or dynamic polymorphism. The latter very much looks like the way to go
here, but you haven't stated what you're doing, so it's hard to tell.

Tom,

What's unclear?

I have an ID passed to a method of a class, say class1.
That function then creates one of several classes derived from another base
class depending on the ID.

Whatever one is created I want to perform an overloaded function of class1,
the overloading depending on which derived class was created. Each does
something very similar (kicks off a thread) but a different derived thread
class with a different parameter set - the parameter sets are themselves
classes and have a different lifetime to thread classes (I access them after
the thread has died).

As well as just wondering wether it can be done I wanded to avoid a big
switch or if-else.

In the extreme say ther were dozens of slightly different classes, it would
be nice just to avoid any conditional statements and just have C++ do it
implicitely if possible.

Anything other info you need just say.
 
T

Thomas Matthews

Joe said:
Tom,

What's unclear?

I have an ID passed to a method of a class, say class1.
That function then creates one of several classes derived from another base
class depending on the ID.

Whatever one is created I want to perform an overloaded function of class1,
the overloading depending on which derived class was created. Each does
something very similar (kicks off a thread) but a different derived thread
class with a different parameter set - the parameter sets are themselves
classes and have a different lifetime to thread classes (I access them after
the thread has died).

As well as just wondering wether it can be done I wanded to avoid a big
switch or if-else.

In the extreme say ther were dozens of slightly different classes, it would
be nice just to avoid any conditional statements and just have C++ do it
implicitely if possible.

Anything other info you need just say.

You need to implement the Factory Design Pattern. Search this newsgroup
for "factory".

Here is how I have implemented the factory:
1. Each class has a parent class. The factory returns a pointer to
a dynamically created child.

2. Each child has a static "create" class that returns a pointer to
a dynamically allocated child:
class Child1
: public Parent
{
public:
static Parent * create(ID_TYPE id);
};

Parent *
Child1 ::
create(ID_TYPE id)
{
if (id == CHILD1_ID)
{
return new Child1;
}
else
return NULL;
}

3. The Factory has a table of pointers to create functions for each
child class. Each function is executed by dereferencing the
pointer (and passing the ID). If the pointer is null, the next
function is executed.

In your case, you could have a virtual method in the parent class
for launching threads (or lets us call it initializing). The factory
could execute this method after successful creation of the child:
if (pointer_to_child)
{
pointer_to_child->Initialize();
// or pointer_to_child->Create_Thread();
}


Alternatives:
1. Create a table of <id, pointer to create function> and use
the std::lower_bound to find the appropriate function pointer.
For small quantities, the above method is faster than using
the binary_search.

2. Have the create() function start the thread for that child,
rather than the factory.


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
T

Thomas Matthews

tom_usenet said:
But it looks to me like you should be using virtual functions and a
common base class - type-switches are pretty much *always* indicative
of a problematic design.

Tom

Not necessarily. Creation of objects based on type is the essence
behind the Factory Design Pattern, and not indicative of a problematic
design.

A common implementation for the Factory is message parsing. Establish
a parent message class, then create specific messages based upon
incoming data. Each specific message would be a different type (which
is a descendant of the parent). I've seen this implementation in many
embedded systems, but not so elegantly designed (and also using the
C language).

I also used the Factory in implementing a emulator for a processor.
The parent class was "Instruction" and child classes were addition,
rotate, etc. A program was a vector of {pointers to} instructions.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
T

tom_usenet

Tom,

What's unclear?

I have an ID passed to a method of a class, say class1.
That function then creates one of several classes derived from another base
class depending on the ID.

Whatever one is created I want to perform an overloaded function of class1,
the overloading depending on which derived class was created. Each does
something very similar (kicks off a thread) but a different derived thread
class with a different parameter set - the parameter sets are themselves
classes and have a different lifetime to thread classes (I access them after
the thread has died).

As well as just wondering wether it can be done I wanded to avoid a big
switch or if-else.

That's good to avoid - it's generally a sign of bad design.
In the extreme say ther were dozens of slightly different classes, it would
be nice just to avoid any conditional statements and just have C++ do it
implicitely if possible.

Anything other info you need just say.

That is clearer; it sounds like you want a factory method (using a map
of ids to class creation functions (which will be template
specializations)) and the visitor pattern. A web search will reveal
all, or buy a book on OO design patterns.

Alternatively, you could use multiple dispatch (a method that is
polymorphic on more than 1 parameter, aka a multimethod). Again a web
search will help.

Tom
 
T

tom_usenet

Not necessarily. Creation of objects based on type is the essence
behind the Factory Design Pattern, and not indicative of a problematic
design.

Would you call that a type switch though? Actually, what the OP had
wasn't really a type switch either, but rather he needs a factory and
the visitor pattern (or multimethods).
A common implementation for the Factory is message parsing. Establish
a parent message class, then create specific messages based upon
incoming data. Each specific message would be a different type (which
is a descendant of the parent). I've seen this implementation in many
embedded systems, but not so elegantly designed (and also using the
C language).

I did a C++ based one on QNX a few years back, using a generic object
factory and a highish performance templated serialization technique
(at least it serialized a vector of PODs in one memcpy call, didn't
use virtual functions, and only required classes to implement a single
operator overload to be polymorphically serializable to and from a
stream). I'm sure I'd do a bit better job of it now, but not that much
better (performance was a major constraint).

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,173
Messages
2,570,938
Members
47,481
Latest member
ElviraDoug

Latest Threads

Top