Pass a derived object to func so that it is base?

T

Tom Wilson

Is there a way to pass a derived object so that the called function thinks
it is the base class?

Here's the lowdown.

class Hull
{
// ....
virtual int DoIt() { TRACE("Hull"); }
// ....
}



class ConvexHull : public Hull
{
// ....
int DoIt() { TRACE("ConvexHull"); }
// ....
}

class Fitted
{
// ....
int FitHull(Hull *in_phull) { in_phull->DoIt(); }
// ....
}

main()
{
Fitted fittedData;
ConvexHull chull;
Hull *phull=&chull;

fittedData.FitHull(&chull);

fittedData.FitHull(phull);
}

Output is:
ConvexHull
ConvexHull

Is there a way to pass phull so that it forgets about its derived class? I
want the output to be:

ConvexHull
Hull

Thanks.
 
T

Thomas Tutone

Tom said:
Is there a way to pass a derived object so that the called function thinks
it is the base class?

Here's the lowdown.

class Hull
{
// ....
virtual int DoIt() { TRACE("Hull"); }
// ....
}



class ConvexHull : public Hull
{
// ....
int DoIt() { TRACE("ConvexHull"); }
// ....
}

class Fitted
{
// ....
int FitHull(Hull *in_phull) { in_phull->DoIt(); }
// ....
}

main()
{
Fitted fittedData;
ConvexHull chull;
Hull *phull=&chull;

fittedData.FitHull(&chull);

fittedData.FitHull(phull);
}

Output is:
ConvexHull
ConvexHull

Is there a way to pass phull so that it forgets about its derived class? I
want the output to be:

ConvexHull
Hull

Sounds like you want a cast. Often (although not always), the need for
a cast - except in very low-level code - is evidence of a design flaw.
In addition, it sounds like you want intentional slicing, which in many
cases suggests a design flaw.

Still, if you're determined to do this, you could always do:

Hull hull = chull; // intentional slicing of object
fittedData.FitHull(&hull); // pass the sliced object

Frankly, it pains me even to suggest this...

Best regards,

Tom
 
M

Matthias

Tom said:
Is there a way to pass a derived object so that the called function thinks
it is the base class?

Here's the lowdown.

class Hull
{
// ....
virtual int DoIt() { TRACE("Hull"); }
// ....
}

[...]

Maybe I miss the point, but if you would not declare DoIt() to be
virtual, then you would get your intended behaviour, right?
(Why overwrite this method at all, if it should do the same things for
all classes?)

Regards,
Matthias
 
B

Bob Hairgrove

Is there a way to pass a derived object so that the called function thinks
it is the base class?

Here's the lowdown.

class Hull
{
// ....
virtual int DoIt() { TRACE("Hull"); }
// ....
}



class ConvexHull : public Hull
{
// ....
int DoIt() { TRACE("ConvexHull"); }
// ....
}

class Fitted
{
// ....
int FitHull(Hull *in_phull) { in_phull->DoIt(); }
// ....
}

main()
{

This must be:
int main()

Otherwise, the behavior is undefined in C++.
Fitted fittedData;
ConvexHull chull;
Hull *phull=&chull;

fittedData.FitHull(&chull);

fittedData.FitHull(phull);
}

Output is:
ConvexHull
ConvexHull

Is there a way to pass phull so that it forgets about its derived class? I
want the output to be:

ConvexHull
Hull

Thanks.

What the others have said. But you could make Hull an abstract class
and only implement the function in derived classes. Then it would call
whatever version of FitHull() is appropriate for that class.

Rather than making Hull::DoIt() non-virtual, if you don't want an
abstract class, I would provide a separate function for calling the
base class function.

As someone else said, you could use a cast. That would look like this:

class Fitted
{
// ....
int FitHull(Hull *in_phull) {
ConvexHull * cvh = dynamic_cast<ConvexHull*>(in_phull);
if (cvh)
in_phull->DoIt();
else
in_phull->Hull::DoIt();
}
// ....
}

For each derived type, you'd need another if..else branch with the
appropriate cast. That's abusing polymorphism, though ... you REALLY
don't want to do that, do you?
 
T

Tom Wilson

Thomas Tutone said:
Sounds like you want a cast. Often (although not always), the need for
a cast - except in very low-level code - is evidence of a design flaw.
In addition, it sounds like you want intentional slicing, which in many
cases suggests a design flaw.

Still, if you're determined to do this, you could always do:

Hull hull = chull; // intentional slicing of object
fittedData.FitHull(&hull); // pass the sliced object

Frankly, it pains me even to suggest this...

Yes, this would be bad. Let's say for instance, my Hull class has 500,000
points that define the Hull. ConvexHull contains pointers to those points
that define only the ConvexHull. Speed is important. We have a lot of
hulls and a lot of points. I don't want to be creating a copy of this base
set of points.... Sometimes I want to work with the points that define the
entire Hull (perimeter) and sometimes I want to work with all the points. I
was hoping to have member functions of class Fitted be able to handle a Hull
object or a ConvexHull object and call FitHull() on the appropriate set of
points depending on the type of object passed in.
For example,

void Fitted::FitHull(Hull *in_phull)
{
//...
// in_phull might be a Hull, might be a ConvexHull.....
//
double pd = in_phull->GetPt(i);
}
 
T

Tom Wilson

The method does not do the same thing for both classes. DoIt() outputs
"Hull" in the base class and "ConvexHull" in the ConvexHull class.

Additional discussion is in response to Tommy Tutone message.


Matthias said:
Tom said:
Is there a way to pass a derived object so that the called function
thinks
it is the base class?

Here's the lowdown.

class Hull
{
// ....
virtual int DoIt() { TRACE("Hull"); }
// ....
}

[...]

Maybe I miss the point, but if you would not declare DoIt() to be
virtual, then you would get your intended behaviour, right?
(Why overwrite this method at all, if it should do the same things for
all classes?)

Regards,
Matthias
 
T

Tom Wilson

Thanks Bob for your help.
Unfortunately, in the real world there is code that you don't have months or
even a week to rewrite that you come across that almost does what you want
it to do, but not quite. Rewriting/redesigning would be great if I had a
sugar momma and didn't work for the man.

Anyway, it was just a C++ logistics question, seeing what people had to say
about it. I guess I left a little detail out for the option of redesigning
the code....the key constraint I didn't mention is I can't be making copies
of this object willy nilly (which your suggestion doesn't do, so that was
good).

So your code in FitHull is terrible, but it fits the bill. Just what I was
looking for... An answer to the question.

class Hull has about 500,000 points so I don't want to be making copies of
objects. The convexHull points are just a subset of the Hull points, though
it could be a fairly large subset. So, theoretically, I would probably put
the Hull data in its own class and create 2 new classes the perform
operations on the Hull data object.

Thanks again.
 
M

Michiel.Salters

Tom said:
Let's say for instance, my Hull class has 500,000
points that define the Hull. ConvexHull contains pointers to those points
that define only the ConvexHull. Speed is important. We have a lot of
hulls and a lot of points. I don't want to be creating a copy of this base
set of points.... Sometimes I want to work with the points that define the
entire Hull (perimeter) and sometimes I want to work with all the points. I
was hoping to have member functions of class Fitted be able to handle a Hull
object or a ConvexHull object and call FitHull() on the appropriate set of
points depending on the type of object passed in.

If you have some notion of an "appropriate set of points" which differs
between
Hull and ConvexHull, then why isn't there a GetAppropriateSetOfPoints?
Then every other caller that doesn't care about ConvexHull's or
AlmostConvexHull's or CatamaranHull's or ... can simply call that
function.

HTH,
Michiel Salters
 
B

Bob Hairgrove

Thanks Bob for your help.
Unfortunately, in the real world there is code that you don't have months or
even a week to rewrite that you come across that almost does what you want
it to do, but not quite. Rewriting/redesigning would be great if I had a
sugar momma and didn't work for the man.

I've been there before, too .. not a pleasant situation to be in!
Maybe after the deadline there will be a little time to go over the
design again (hopefully).
Anyway, it was just a C++ logistics question, seeing what people had to say
about it. I guess I left a little detail out for the option of redesigning
the code....the key constraint I didn't mention is I can't be making copies
of this object willy nilly (which your suggestion doesn't do, so that was
good).

So your code in FitHull is terrible, but it fits the bill. Just what I was
looking for... An answer to the question.

class Hull has about 500,000 points so I don't want to be making copies of
objects. The convexHull points are just a subset of the Hull points, though
it could be a fairly large subset. So, theoretically, I would probably put
the Hull data in its own class and create 2 new classes the perform
operations on the Hull data object.

Good luck!
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top