dynamic_cast and typeid

F

flopbucket

Hi,

I have a question about using a typeid comparison instead of
dynamic_cast in certain circumstances.

Assume I have the following:

class Base {};

class Foo : public Base {};

I can not change either Base or Foo. However, when a Foo object is
received, some special processing must occur. There is a method such
as:

void func(Base *b);

Calls to 'func' are always done with a Base * even if the real object
is a Foo (base class pointer).

Now, I know I could do:

void func(Base *b)
{
if(Foo *f=dynamic_cast<Foo*>(b))
{
// handle Foo
}

....
}

But I could also do (I believe)

void func(Base *b)
{
if(typeid(*b) == typeid(Foo))
{
/// handle Foo
}
}

My questions are:

1. Wouldn't the second version be quicker? My understand is that
dynamic_cast has to do more, since it allows you to cast throughout
the hierarchy.

2. Regardless of the two implementations above, can you think of a
better solution? I hate to do this typeid comparison or a
dynamic_cast in every call. Ideally:

void func(Base *b);
void func(Foo *f);

would be perfect, and the compiler would call the correct one
depending on the calling type. But in this application, objects of
type Foo are returned by a factory by the base class pointer, so the
compiler will always call func(Base *).

Any ideas greatly apprecaited.

Thanks
 
A

Alf P. Steinbach

* flopbucket:
Hi,

I have a question about using a typeid comparison instead of
dynamic_cast in certain circumstances.

Assume I have the following:

class Base {};

class Foo : public Base {};

I can not change either Base or Foo. However, when a Foo object is
received, some special processing must occur. There is a method such
as:

void func(Base *b);

Calls to 'func' are always done with a Base * even if the real object
is a Foo (base class pointer).

Now, I know I could do:

void func(Base *b)
{
if(Foo *f=dynamic_cast<Foo*>(b))
{
// handle Foo
}

....
}

You can't: Base doesn't have any virtual member functions.

But I could also do (I believe)

void func(Base *b)
{
if(typeid(*b) == typeid(Foo))
{
/// handle Foo
}
}

With a polymorphic Base class, yes.

My questions are:

1. Wouldn't the second version be quicker? My understand is that
dynamic_cast has to do more, since it allows you to cast throughout
the hierarchy.

Don't be concerned with micro-efficiency, be concerned with correctness.

And for that, replace the pointer argument with a reference argument.

Unless you really want to support "no argument" and that's the only way
to do it.

2. Regardless of the two implementations above, can you think of a
better solution? I hate to do this typeid comparison or a
dynamic_cast in every call. Ideally:

void func(Base *b);
void func(Foo *f);

would be perfect, and the compiler would call the correct one
depending on the calling type. But in this application, objects of
type Foo are returned by a factory by the base class pointer, so the
compiler will always call func(Base *).

Generally, use virtual member functions instead of explicit type
discrimination.

In some cases you'll need to use visitor pattern.

But don't jump on that wagon willy-nilly; first check whether a simple
introduction of some suitable virtual member functions in Base would do
the trick. Because that's generally what virtual member functions are
for. Namely treating objects polymorphically at run time.
 
F

flopbucket

Now, I know I could do:
You can't: Base doesn't have any virtual member functions.

Correct, the real code does have virtual functions, I accidentally
left it out in the short example I posted.
With a polymorphic Base class, yes.



Don't be concerned with micro-efficiency, be concerned with correctness.

And for that, replace the pointer argument with a reference argument.

Unless you really want to support "no argument" and that's the only way
to do it.

Yes, good advice. I will change it. I usually try to use references
but this was some existing code.
Generally, use virtual member functions instead of explicit type
discrimination.

Yes, normally I would do this but in this case I have no control over
the objects. They actually represent messages received over a network
and by the time I receive them they are already in the form they are,
and I can not modify the legacy code.
In some cases you'll need to use visitor pattern.

Thanks, will take a look at this.
 
F

Frank Birbacher

Hi!
Yes, normally I would do this but in this case I have no control over
the objects. They actually represent messages received over a network
and by the time I receive them they are already in the form they are,
and I can not modify the legacy code.

Did you find out why they won't let you figure out the actual type of
the message? Did the library authors do this intentionally?
Thanks, will take a look at this.

The visitor pattern needs you to modify the classes which you can't.

Frank
 
J

joe

Yes, normally I would do this but in this case I have no control over
the objects. They actually represent messages received over a network
and by the time I receive them they are already in the form they are,
and I can not modify the legacy code.

Is there anything common in the messages that you could key off of,
like
an error/message code?

joe
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top