Why do I want RTTI?

R

RM

Help me understand why would anyone want RTTI.
Would it RTTI be considered a violation of OO concept?

Secondly, I like to know how popular is Exception and namespace in C++.

Troll: I hate exceptions especially user-defined exceptions (but I am ok
with built-in exceptions). I still prefer functions returning error code.
And Namespace seems to be largely ignored.

Thanks
 
K

Karthik

RM said:
Help me understand why would anyone want RTTI.

Primarily for debugging purposes, I suppose.
Would it RTTI be considered a violation of OO concept?

One place where you can (theoretically ) is reinterpret_cast. But
that is way too dangerous.
Secondly, I like to know how popular is Exception and namespace in C++.

Troll: I hate exceptions especially user-defined exceptions (but I am ok
with built-in exceptions).

That is strange, since from a programmer point of view, it is
totally transparent anyway. Assume you are writing an imaging library,
where the user tries to access beyond the boundaries of width and height
of the image, would you prefer to return different values (remember, the
return value would depend on the type of the function, 0 for ints, ""
for char *). A cleaner way might be to throw a custom exception and ask
the user to catch it. That might be more cleaner.

But I do agree that it has got a runtime overhead. But unless you are
programming for systems where memory footprint ought to be low ( for
embedded sys, like that), there is no reason why you should not use
exceoptions.
 
R

Rolf Magnus

RM said:
Help me understand why would anyone want RTTI.

It can be useful in some places.
Would it RTTI be considered a violation of OO concept?

Yes. Interestingly, newer OO languages like java make heavy use of it.
Secondly, I like to know how popular is Exception and namespace in
C++.

Exceptions haven't been used for quite a long time. It seems that they
get used more nowadays, but still there are lots of projects that don't
use exceptions. With namespaces, it seems to be similar.
Troll: I hate exceptions especially user-defined exceptions (but I am
ok with built-in exceptions). I still prefer functions returning
error code.

IMHO, exceptions are useful in some places, but classic error return
codes are often preferable.
And Namespace seems to be largely ignored.

I'm using them now in all my C++ projects. But it seems I'm part of a
minority in this regard.
 
D

Denis Remezov

Steven T. Hatton said:
Suppose you have a collection of objects derived from a particular base
class, for example CanvasItem. CanvasItems are form the content of some
kind of graphical image and consist of Rectangles, ComplexPolygons,
PixMaps, etc. These might all get pushed into a CanvasItemVector<> that
only knows them as CanvaItems. Later you want to do something with all the
PixMaps. You can use RTTI to select the PixMaps fromm the CanvasItemVector
contents.

You can but only should do so if you have first considered virtual functions
and ruled them out for a compelling reason (such reason cannot be seen from
your example). Maybe it's just me, but for the number of times I have used
dynamic_cast, I have seen it being abused many times more.

Denis
 
S

Steven T. Hatton

Rolf said:
It can be useful in some places.

Suppose you have a collection of objects derived from a particular base
class, for example CanvasItem. CanvasItems are form the content of some
kind of graphical image and consist of Rectangles, ComplexPolygons,
PixMaps, etc. These might all get pushed into a CanvasItemVector<> that
only knows them as CanvaItems. Later you want to do something with all the
PixMaps. You can use RTTI to select the PixMaps fromm the CanvasItemVector
contents.

I don't really see why it would be considered a violation of OO. Care to
elaborate.
Interestingly, newer OO languages like java make heavy use of it.

Java certainly does provide and use a powerful introspection and reflection
facility.
Exceptions haven't been used for quite a long time. It seems that they
get used more nowadays, but still there are lots of projects that don't
use exceptions.

Part of the reason is that they are hard to understand. They are frequently
treated as an afterthought in C++ text books.

That seems to be due to the problem that not all compilers implement(ed)
RTTI until recently. Trolltech's documentation mentions this problem.
IMHO, exceptions are useful in some places, but classic error return
codes are often preferable.

I believe exceptions should be use far more frequently, and both the
understand and the support for exceptions in C++ needs to be improved.
'Traditional' error returns seem potentially limiting from my perspective.
I'll have to wait for the coffee to kick in before I try to explain that.
I'm using them now in all my C++ projects. But it seems I'm part of a
minority in this regard.

Again, there seem to be a history of partial support, as well as a problem
of understanding. Namespaces, in combination with the use of headers and
#includes can lead to some bizarre results. I've tried to use namespaces
in my code as much as seems reasonable. It really does require a lot more
work than the comperable use of packages, for example, in Java.
 
R

RM

Steven T. Hatton said:
Suppose you have a collection of objects derived from a particular base
class, for example CanvasItem. CanvasItems are form the content of some
kind of graphical image and consist of Rectangles, ComplexPolygons,
PixMaps, etc. These might all get pushed into a CanvasItemVector<> that
only knows them as CanvaItems. Later you want to do something with all the
PixMaps. You can use RTTI to select the PixMaps fromm the CanvasItemVector

I don't really see why it would be considered a violation of OO. Care to
elaborate.

I may be wrong but this is how I see it.
The main reason why we have CanvasItemVector in the first place, is we want
to deal with all CanvasItem object transparently - Polymorphism ?. If we
need to know the object type, we no longer have Polymorphism. The problem
is what happen when we introduce a new class derived from CanvasItem; the
new class will have to be handled in many different places whereever RTTI
appeared.
 
B

bartek

(...)
I may be wrong but this is how I see it.
The main reason why we have CanvasItemVector in the first place, is we
want to deal with all CanvasItem object transparently - Polymorphism
?. If we need to know the object type, we no longer have
Polymorphism. The problem is what happen when we introduce a new
class derived from CanvasItem; the new class will have to be handled
in many different places whereever RTTI appeared.

This is exactly where you want the visitor pattern. It's a "strictly OO"
way of doing double dispatch in C++.

Though, visitor's got problems of its own, and sometimes looks cumbersome
if there are lots of types to dispatch. Neverthless, visitor can help
guarantee that every type in a, say, CanvasItemVector will be 'serviced',
or else you'll get a compile-time error -- something that doesn't really
happen with switches.
 
A

Alf P. Steinbach

* "RM said:
Help me understand why would anyone want RTTI.

One example is when implementing the Visitor pattern (google it).

Would it RTTI be considered a violation of OO concept?

That's not a meaningful question. Is a 'for'-loop a violation of
OO concepts?


Secondly, I like to know how popular is Exception and namespace in C++.

Standard C++ is based on exceptions and namespaces.
 
J

Jorge Rivera

RM said:
I may be wrong but this is how I see it.
The main reason why we have CanvasItemVector in the first place, is we want
to deal with all CanvasItem object transparently - Polymorphism ?. If we
need to know the object type, we no longer have Polymorphism. The problem
is what happen when we introduce a new class derived from CanvasItem; the
new class will have to be handled in many different places whereever RTTI
appeared.

Usually that is a design flaw, and hence the notion of RTTI being useless.

However, consider this example...

class Event
{
..... // Don;t care about details right now
};

Class EventHandler
{
....// HEre goes everything you need for the mechanism
protected:
virtual bool handleEvent(Event* anEvent)=0;
};


Now, your specific message handler only know how to handle a specific
type of request. However, the APi dictates that every EventHandler must
handle Event objects. Eg.

class MyEvent : public Event
{
};

class MyHandler : public EventHandler
{
protected:
virtual bool handleEvent(Event* myEvent);
}

Here we may want to guarantee that only events of type MyEvent are
caught be MeHandler.

Hence your handleEvent may end-up looking like this...

bool MyHandler::handleEvent(Event* myEvent)
{
if(!dynamic_cast<MyEvent*>(myEvent))
; // Can't handle this event. Logic flaw....
}


There may be better designs to solve this. However, here RTTI allows
your specific handlers to determine weather the received event is
something they can handle.

This does not pollute the original design in any way, as RTTI is only
used for specific handlers. You can still treat MyHandler as any other
type of event handler...

JLR
 
S

Steven T. Hatton

I may be wrong but this is how I see it.
The main reason why we have CanvasItemVector in the first place, is we
want
to deal with all CanvasItem object transparently - Polymorphism ?.

In that particular instance, we /do/ want all of them to act generically.
We don't care about the details of each CanvasItem. I think of it like
passengers on a train. All the conductor cares about is whether you have a
ticket. (And that you behave yourself). He doesn't care if you are a
doctor, computer programmer, etc. IF you happen to get to an international
border, there will be questions regarding your national citizenship.
That's when the passenger needs to produce some kind of 'type information'.

Polymorphism, like many OO terms, does not have a single, universal
definition. Budd provides a few definition. I'll use this from his Intro
to OOP: "In programming languages, a polymorphic object is any entity, such
as a variable or function argument, that is permitted to hold values of
differing types during the course of exectution."

If we
need to know the object type, we no longer have Polymorphism.

I'm not sure that is really correct. Polymorphism seems to be a
circumstantial characteristic which is not required for all instances in
which the object exhibiting polymorphism is used.
The problem
is what happen when we introduce a new class derived from CanvasItem; the
new class will have to be handled in many different places whereever RTTI
appeared.

That may, or may not, be a problem. If the objects of the newly introduced
type are used in many different parts of the program, and require different
treatment due to their unique characteristics, that's just the nature of
programming. You can't really get away from that unless you put the
variant functionality in the object itself. There are often two options to
implementing functionality for manipulating objects. Either the
functionality is internal to objects so they /act for themselves/, or it is
implemented outside of the class, and the objects are /acted on/. In the
latter case, if you need different behavior per class, it the manipulator
needs to know what kind of object it is acting on. Sometimes it is not
reasonable (or even possible) to put functionality into the class. In such
cases, RTTI is a reasonable way to discriminate between object types.

I think it's important to keep in mind that OO principles do not require
that all objects and or functions be polymorphic. It's also important to
remember that C++ was not designed as a strictly OOPL. Furthermore, IMO,
what matters in the final analysis is not whether the program adheres
strictly to some set of definitions considered as OOP, but rather, whether
the program does what it was designed to do, is reasonably efficient,
reliable, robust, and above all maintainable.
 
S

Steven T. Hatton

Denis said:
:

You can but only should do so if you have first considered virtual
functions and ruled them out for a compelling reason (such reason cannot
be seen from
your example).

My example was directly taken from Qt's Canvas Module:
http://doc.trolltech.com/3.3/canvas.html

It doesn't always make sense to put functionality inside objects. For
example, say you want to produce an animation that changes the behavior of
a certain class of objects after a given number of frames. If you try to
program that behavior into each class, the classes will be very complicated
and specialized. The could not be used without modification in another,
similar animation.
Maybe it's just me, but for the number of times I have
used dynamic_cast, I have seen it being abused many times more.

Perhaps. My experience has been that a lot of C++ code has workarounds for
things that could better be handled by features of the language, but were
not available on all target platforms or compilers.
 
L

Luther Baker

Steven T. Hatton wrote:

....
That may, or may not, be a problem. If the objects of the newly introduced
type are used in many different parts of the program, and require different
treatment due to their unique characteristics, that's just the nature of
programming. You can't really get away from that unless you put the
variant functionality in the object itself. There are often two options to
implementing functionality for manipulating objects. Either the
functionality is internal to objects so they /act for themselves/, or it is
implemented outside of the class, and the objects are /acted on/. In the
latter case, if you need different behavior per class, it the manipulator
needs to know what kind of object it is acting on.

GoF Mediator pattern.
Sometimes it is not
reasonable (or even possible) to put functionality into the class. In such
cases, RTTI is a reasonable way to discriminate between object types.

I think it's important to keep in mind that OO principles do not require
that all objects and or functions be polymorphic. It's also important to
remember that C++ was not designed as a strictly OOPL. Furthermore, IMO,
what matters in the final analysis is not whether the program adheres
strictly to some set of definitions considered as OOP, but rather, whether
the program does what it was designed to do, is reasonably efficient,
reliable, robust, and above all maintainable.

Nice thread.

-Luther
 
C

Cy Edmunds

RM said:
Help me understand why would anyone want RTTI.
Would it RTTI be considered a violation of OO concept?

RTTI has gotten a bad rap based on code like this:

Car *pcar = dynamic_cast<Car*>(pvehicle);
if (pcar)
...
else
Boat *pboat = dynamic_cast<Boat*>(pvehicle);
if (pboat)
...
else
...

ad nauseum. However that is hardly the only possible use of RTTI. In many
object oriented systems an object is allowed to export multiple interfaces,
some of which may not be implemented. RTTI is how to find out. That is
hardly a "violation of OO concept" in my book.
Secondly, I like to know how popular is Exception and namespace in C++.

They're pretty popular in my neighborhood.
Troll: I hate exceptions especially user-defined exceptions (but I am ok
with built-in exceptions). I still prefer functions returning error code.

I would advise you to make the transition from C to C++. The kind of code
you prefer winds up looking like a bunch of error checks with the actual
functionality buried in a blizzard of if tests. Exceptions help us keep
normal program flow and error checking as separate as possible.

Your dislike of user-defined exceptions really surprises me. Do you also
dislike user defined functions and classes? That's where the power is! But I
would agree that they should all be derived from std::exception if that's
what you mean.
And Namespace seems to be largely ignored.

In so far as that's true I'm sorry to hear it.
 
A

Alf P. Steinbach

* "Cy Edmunds said:
I would advise you to make the transition from C to C++. The kind of code
you prefer winds up looking like a bunch of error checks with the actual
functionality buried in a blizzard of if tests.

Just say no to error checking. ;-)
 
D

Denis Remezov

Steven T. Hatton said:
In that particular instance, we /do/ want all of them to act generically.
We don't care about the details of each CanvasItem. I think of it like
passengers on a train. All the conductor cares about is whether you have a
ticket. (And that you behave yourself). He doesn't care if you are a
doctor, computer programmer, etc. IF you happen to get to an international
border, there will be questions regarding your national citizenship.
That's when the passenger needs to produce some kind of 'type information'.

(Also in response to your other reply):
A visitor pattern may be appropriate here (with the Conductor being a Visitor).
True, it would involve some additional abstraction, but instead of switching
based on the dynamic type (which could become a mess) you would have just two
virtual calls.

One downside of the GoF-style VP with two virtual calls is a circular dependency
between the participants. In a tightly coupled system this should not be a
concern; otherwise, another layer of abstraction might be in order. At some
point (e.g. interfacing two disparate systems) a dynamic_cast would become
quite justified.

[...snip...]

Denis
 
S

Steven T. Hatton

(Also in response to your other reply):
A visitor pattern may be appropriate here (with the Conductor being a
Visitor). True, it would involve some additional abstraction, but instead
of switching based on the dynamic type (which could become a mess) you
would have just two virtual calls.

One downside of the GoF-style VP with two virtual calls is a circular
dependency
between the participants. In a tightly coupled system this should not be
a
concern; otherwise, another layer of abstraction might be in order. At
some point (e.g. interfacing two disparate systems) a dynamic_cast would
become quite justified.

[...snip...]

This is what GoF have to say about the visitor pattern:

"Adding new ConcreteElement classes is hard. The Visitor pattern makes it
hard to add new subclasses of Element. Each new ConcreteElement gives rise
to a new abstract operation on Visitor and a corresponding implementation
in every ConcreteVisitor class. Sometimes a default implementation can be
provided in Visitor that can be inherited by most of the ConcreteVisitors,
but this is the exception rather than the rule."

"So the key consideration in applying the Visitor pattern is whether you are
mostly likely to change the algorithm applied over an object structure or
the classes of objects that make up the structure. The Visitor class
hierarchy can be difficult to maintain when new ConcreteElement classes are
added frequently. In such cases, it's probably easier just to define
operations on the classes that make up the structure. If the Element class
hierarchy is stable, but you are continually adding operations or changing
algorithms, then the Visitor pattern will help you manage the changes."
....

Known Uses:
....

"IRIS Inventor [Str93] is a toolkit for developing 3-D graphics
applications. Inventor represents a three-dimensional scene as a hierarchy
of nodes, each representing either a geometric object or an attribute of
one. Operations like rendering a scene or mapping an input event require
traversing this hierarchy in different ways. Inventor does this using
visitors called "actions." There are different visitors for rendering,
event handling, searching, filing, and determining bounding boxes.

To make adding new nodes easier, Inventor implements a double-dispatch
scheme for C++. _*The_scheme_relies_on_run-time_type_information_* and a
two-dimensional table in which rows represent visitors and columns
represent node classes. The cells store a pointer to the function bound to
the visitor and node class."
 

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
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top