Identifiying which derived class you have in code

C

Christopher

I've seen various ways of doing this, but what I want is to be able to
take a base class pointer and know which derived class to cast to.

For example I am going to make a base light class, that has a position
and intensity.
A derived classes class may be a point light which also has a falloff
value.

The derived class has all the base class methods and data in common,
but has the additional falloff value get/set methods.

Now my rendering interface takes a base light class pointer, but the
body needs to know if it is a point light or not, so it can cast and
get that fall off value.

Ways I've seen this done:

1) dynamic cast and check for NULL;

Well, we could potentially be going through 10 dynamic casts or
more before we know what we have. I heard it was rather expensive to
do that.

2) Put a static const int identifier in every derived class and check
for each in a switch, then you know what to
cast to.

I don't know if this is really more efficient than 1. It also
requires keeping track of all these IDs and which are used already
when you make a new derived class.

3) Any other sugestions?
 
T

Triple-DES

I've seen various ways of doing this, but what I want is to be able to
take a base class pointer and know which derived class to cast to.

For example I am going to make a base light class, that has a position
and intensity.
A derived classes class may be a point light which also has a falloff
value.

The derived class has all the base class methods and data in common,
but has the additional falloff value get/set methods.

Now my rendering interface takes a base light class pointer, but the
body needs to know if it is a point light or not, so it can cast and
get that fall off value.

Ways I've seen this done:

1) dynamic cast and check for NULL;

    Well, we could potentially be going through 10 dynamic casts or
more before we know what we have. I heard it  was rather expensive to
do that.

2) Put a static const int identifier in every derived class and check
for each in a switch, then you know what to
    cast to.

    I don't know if this is really more efficient than 1. It also
requires keeping track of all these IDs and which are used already
when you make a new derived class.

3) Any other sugestions?

Yes, you can always use typeid(), which yields a different type_info&
for each class. Then you can make a wrapper for the type_info&s and
put them all in a map<TypeInfoWrapper, function>.

This way you can lookup the typeid of an object in the map, and call a
different function depending on the type, Effectively doing log(n)
comparisons instead of n comparisons with dynamic_cast.

By now you will probably realize that you have pretty much implemented
a virtual function table. So the simpler solution would be to use the
virtual functions that is built into the language :) This is also
considered much better design, from an OO point of view.

DP
 
J

James Kanze

* Christopher:
Use a reference, unless you're planning on supporting
nullpointer argument.

Very expensive. Each time you add a class, you have to go back
and modify the code. You can't get much more expensive than
that.

It's not. Each time you add a class, you have to go back and
modify the code.
As I understand it the problem is how to optimize the
rendering when the light is point with no fall off.
Just let the base class provide identification that it is a
point.
With that identification of point-ness in hand the rendering
code can branch to treatment as point or treatment as
fall-off.
For the 9 or 10 classes with fall-off, provide the fall-off
information through a common interface.

If this is the case, then the obvious design is to provide a
derived class (also abstract) with the additional functions.
Classes which support the added functionality derive from the
derived class, rather than directly from Light, and his
rendering code has one dynamic_cast, and an if on the results of
it, e.g.:

PointLight* pointLight
= dynamic_cast< PointLight* >( light ) ;
if ( pointLight != NULL ) {
// implementation using the PointLight interface...
} else {
// implementation using the original Light interface...
}
This interface can be present also in the base class, but the
rendering code can, based on identification of point-ness,
choose to use more efficient way then.
As always, remember to measure.
It might be that this attempt at optimization will have
little, no or even negative effect (such is difficult to
predict, measurement is needed).

It's rather obvious that maintaining code with 10 or more
dynamic_cast's is very expensive. I don't think you need to
measure that.
 
R

Rune Allnor

I've seen various ways of doing this, but what I want is to be able to
take a base class pointer and know which derived class to cast to. ....
3) Any other sugestions?

What about the visitor pattern?

Rune
 
J

James Kanze

* James Kanze:
The alternative to optimization isn't another and extremely
silly attempt at optimization, it's simply to not optimize
(manually), i.e. using a common interface for everything
regardless of whether there is a special case.

Whether using another, derived interface optimized development
times or not depends on the case at hand. If the added
functionality is non-trivial, I find it much clearer to have a
separate interface to access it. Having done that, it really
doesn't matter whether you provide a special function in the
base class to return a (possibly null) pointer to this
interface, or use dynamic_cast. But dynamic_cast is already
implemented, so is probably more cost-effective.
And then, relative to no optimization a check for special case
will cause branching, and it will most probably cause slightly
(microscopically) larger code size, which can influence
caching, and with your proposed way of checking (dynamic cast)
instead of my proposed way of checking, the check itself will
likely be "expensive" relative to the code it guides.
Thus, the only way to be sure about the effect is to measure.

But you can't measure except by implementing both, and that's
definitely more expensive than choosing which ever seems most
reasonable, and just using it.
 
J

James Kanze

* James Kanze:
He needs to implement the general case anyway.
Optimization is an add-on.
It would be un-smart to start with complex optimized version.

OK. I think I finally understand what you mean, that even
defining and supporting the additional interface (and way of
doing the calculation) is an optimization, and so shouldn't be
done until the basic version is working, and shown to be too
slow. You may be right---I don't know enough about the
application domain to judge.
 
G

gw7rib

I've seen various ways of doing this, but what I want is to be able to
take a base class pointer and know which derived class to cast to.

For example I am going to make a base light class, that has a position
and intensity.
A derived classes class may be a point light which also has a falloff
value.

The derived class has all the base class methods and data in common,
but has the additional falloff value get/set methods.

Now my rendering interface takes a base light class pointer, but the
body needs to know if it is a point light or not, so it can cast and
get that fall off value.

Ways I've seen this done:

1) dynamic cast and check for NULL;

    Well, we could potentially be going through 10 dynamic casts or
more before we know what we have. I heard it  was rather expensive to
do that.

2) Put a static const int identifier in every derived class and check
for each in a switch, then you know what to
    cast to.

    I don't know if this is really more efficient than 1. It also
requires keeping track of all these IDs and which are used already
when you make a new derived class.

3) Any other sugestions?

I'd suggest trying to do it using virtual functions.

You have to decide - are your derived classes doing things which are
totally different from your base class? Or are they doing the same
sort of thing, though maybe in different and more exotic ways? If your
answer is "totally different", can you, by looking at things more
abstractly, arrange things so that they are instead "same sort of
thing"? If you can get the problem into this form, then straight-
forward virtual functions could be the answer.

For example, with your light sources. Could you perhaps have a
function in the base class, called setfalloff, which does nothing for
most classes but sets the falloff value in the point source class? Or,
more generally, have a setparameters function which allows each class
to set the values it needs to set, somehow? Do you actually need a
getfalloff function, or do you just need a workoutlightatplace
function which will take into account the falloff value for a point
source and will take other things into account for other sources?

You may need to sit down and do quite a bit of thinking before you
start the coding, but it might run faster and be more maintainable as
a result.

Hope that helps.
Paul.
 

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
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top