473,396 Members | 2,037 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Should I use RTTI?

Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.

Dec 20 '06 #1
33 3527
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.
Perfectly valid for a known set of types.

--
Ian Collins.
Dec 20 '06 #2
Ian Collins wrote:
ms****@gmail.com wrote:
>>Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.

Perfectly valid for a known set of types.
I forgot to point out that GetType() should be virtual.

--
Ian Collins.
Dec 20 '06 #3
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.
Your method requires some type of maintenance by the programmer. The
built-in typeid facility does all the magic for you.

I suppose you could build somthing similar out of templates but then "why" ?
Dec 20 '06 #4

ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.
Is this what you had in mind?

#include <iostream>
#include <ostream>
#include <typeinfo>

template< typename Type >
class A {
Type type;
public:
A() : type() { }
virtual ~A() { }
std::string GetType() const { return typeid(type).name(); }
virtual void foo() const = 0;
};

template< typename T >
class B : public A< T >
{
public:
void foo() const
{
std::cout << "B< " << A<T>::GetType();
std::cout << " >::foo()\n";
}
};

// lets replace X, Y and Z with int, long and std::string for for
illustration.

int main()
{
B< int bn;
bn.foo();
B< long bl;
bl.foo();
B< std::string bs;
bs.foo();
}

/* possible sample output:
B< i >::foo()
B< l >::foo()
B< Ss >::foo()
*/

Then why use RTTI? The only reason i can think for getting the typeid
involved is to break the rules of inheritance. These examples with int,
long and std::string could have been X, Y and Z. If you needed B<
std::string to call a different foo() than the templated version
provided, specialize the template. Its that simple.

template< >
void B< std::string >::foo() const
{
std::cout << "the member in base is a string.\n";
}

/* result:
B< i >::foo()
B< l >::foo()
the member in base is a string.
*/

You don't need RTTI to do that. There is no need to tell the compiler
which type is involved, it already knows.

Dec 20 '06 #5

ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...
I am of the opinion that you should disable all possible language
features you can and rewrite them all yourself. Disable RTTI, disable
exceptions, and don't dare use the standard library...especially not
the STL.

Dec 20 '06 #6
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...
I think, RTTI used for "dynamic_cast<>", not only for "typeid" (at
least for some C++ compiler implementation it is true - "dynamic_cast
.... Note: Runtime type information (RTTI) is required for
dynamic_cast").

If you are using class with multiple inheritance and pointers to its
base classes (for example pointers returned from base classes), you
especially can not avoid "dynamic_cast<>", due to unpredicted "this"
address migration from one base class to another or compiler
limitations.

Consider output

//base pointers are not equal
= Test* new Test(1)
9f640: Class
9f630: Base: data: 1
9f638: Class2
9f630: Test: data: 1
= Class* new Test(0)
9fef0: Class
9fee0: Base: data: 0
9fee8: Class2
9fee0: Test: data: 0

= Test* dynamic_cast<Test*(Class*) ( from base class to real class
of obj )
9fee0: ok 9fee0=dynamic_cast<Test*>(9fef0)

= return "this" from base class Class
9fee0: 9fee0->test() == 9fef0
* Test* C-style cast<Test*(Class*) ( from base class to real class
of obj )
error: cannot convert from base 'Class' to derived type 'Test' via
virtual base 'Class'

= return "this" from base class Class2
9fee0: test2() == 9fee8
* Test* C-style cast<Test*(Class2*) ( from base class to real class
of obj )
9fee0: (C-style cast) from 9fee8

As you see, you can write C-style cast for not virtual base classes,
but for multiple inheritance it will be not only unclear (what the way
compiler will use - reinterpret_cast<or dynamic_cast<>?), it is very
easy to put wrong data to the class pointer without dynamic_cast<>.

Dec 21 '06 #7
On Dec 21, 4:54 am, msc...@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;

}class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.

Something a little out of left field may be relevant to you here. If
you are using multiple modules in your application (ie building DLL's
or shared libraries), then using RTTI and/or dynamic_cast can be a
little shaky. If two objects of the same type are created in different
modules/DLLs/shared libraries, then it is entirely possible that the
application will see them as two distinct types with different RTTI
id's. Since the standard is silent about situations like this (it says
nothing about multi-module programs), compilers are free to do this and
indeed we have encountered some mainstream compilers which did (eg some
versions of GCC, but later versions have fixed this). A dynamic_cast
can also incorrectly fail if the object was created in a different
module, and again we have observed this in practice too.

So I guess if you are really paranoid, then your home-grown approach
will avoid these problems, but at the cost of a higher maintenance
burden and more fragile code.

For reference, you may also want to check out two other threads related
to the issues above:

http://groups-beta.google.com/group/...feaa6e/?hl=en#

http://groups-beta.google.com/group/...83565c227fd25b

--
Computational Fluid Dynamics, CSIRO (CMIS)
Melbourne, Australia

Dec 21 '06 #8

Craig Scott wrote:
If two objects of the same type are created in different
modules/DLLs/shared libraries, then it is entirely possible that the
application will see them as two distinct types with different RTTI
id's.
It is not C++ bug. It is compiler bug, it is evidently. RTTI means
"type identification", not RTMI "module identification". If you are
using constant class description (for example, read-only header file
without preprocessor) in each module, any may expect equal runtime
class. In fact, your words mean, that you can not use many C++ features
for the compiler.

There are many other bugs or not complete C++ implementation in
existing compilers.
>Since the standard is silent about situations like this (it says
nothing about multi-module programs), compilers are free to do this and
Write to C++ standart org. If it is real trouble and all around do not
understand, it can be corrected.
A dynamic_cast
can also incorrectly fail if the object was created in a different
module

So I guess if you are really paranoid, then your home-grown approach
But it is not easy to understand what do you advise to do instead of
dynamic_cast<>, typeid and try/catch/throw

Dec 21 '06 #9
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.
I suggest you (a) don't use RTTI and (b) don't use the above either.
Such use violates "tell don't ask". The whole point of inheritance is so
you can use an object without knowing its exact type.
Dec 21 '06 #10


On Dec 21, 2:53 pm, "Grizlyk" <grizl...@yandex.ruwrote:
Craig Scott wrote:
If two objects of the same type are created in different
modules/DLLs/shared libraries, then it is entirely possible that the
application will see them as two distinct types with different RTTI
id's.
It is not C++ bug. It is compiler bug, it is evidently. RTTI means
"type identification", not RTMI "module identification". If you are
using constant class description (for example, read-only header file
without preprocessor) in each module, any may expect equal runtime
class.
The C++ standard does not guarantee this (which is my point). In
practical reality, since everyone intuitively expects it, compiler
writers generally try to support it.
In fact, your words mean, that you can not use many C++ features
for the compiler.
You need to choose carefully *how* you use certain features. There is a
lot of very good advice from some very well respected people on these
issues. It would generally be wise to consider their input.
There are many other bugs or not complete C++ implementation in
existing compilers.
Since the standard is silent about situations like this (it says
nothing about multi-module programs), compilers are free to do this and
Write to C++ standart org. If it is real trouble and all around do not
understand, it can be corrected.
These issues are already well known by the committee and others. There
has been much discussion about a standard C++ ABI, which would go a
long way to resolving most of the issues, but I'm not sure what the
latest is on that front.
A dynamic_cast
can also incorrectly fail if the object was created in a different
module
So I guess if you are really paranoid, then your home-grown approach
But it is not easy to understand what do you advise to do instead of
dynamic_cast<>, typeid and try/catch/throw
You can still use them, just be careful about what you use them on. If
your application uses shared libraries, consider carefully if you can
guarantee that the same compiler will always be used and with the same
settings/flags. If you can and the compiler is a reasonably mainstream
and recent one, then you can most likely use all the above safely even
across module boundaries (but I'm not willing to bet my house on it).

There are alternatives to dynamic_cast and typid (we use one such
alternative, but it is application specific as to what works for you).
If you are *really* keen, go have a look at the internals of Python and
see how they enumerate data types (but it is not for the
faint-hearted!). It isn't C++, but a similar design can be applied
quite nicely if that's what you want.

--
Computational Fluid Dynamics, CSIRO (CMIS)
Melbourne, Australia

Dec 21 '06 #11
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...
Actually, it's probably a defect in your design if you EVER
have to ask what an object is. If there is behavior that
is dependent on the type of an object, it probably should be
implemented in a virtual method of the class.
Dec 21 '06 #12


On Dec 21, 3:23 pm, Ron Natalie <r...@spamcop.netwrote:
msc...@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...Actually, it's probably a defect in your design if you EVER
have to ask what an object is. If there is behavior that
is dependent on the type of an object, it probably should be
implemented in a virtual method of the class.
We aren't alone in this thought.....
>From Effective C++, by Scott Meyers :
"Anytime you find yourself writing code of the form "if the object is
of type T1,
then do something, but if it's of type T2, then do something else,"
slap yourself."

Dec 21 '06 #13
andrewmcdonagh wrote:
....
>
>>From Effective C++, by Scott Meyers :

"Anytime you find yourself writing code of the form "if the object is
of type T1,
then do something, but if it's of type T2, then do something else,"
slap yourself."
What about boost::any ?

Dec 21 '06 #14
Gianni Mariani <gi*******@mariani.wswrote:
andrewmcdonagh wrote: ...
From Effective C++, by Scott Meyers :
"Anytime you find yourself writing code of the form "if the object
is of type T1, then do something, but if it's of type T2, then do
something else," slap yourself."

What about boost::any ?
... you should endeavor to tell objects what you want them to do;
do not ask them questions about their state, make a decision, and
then tell them what to do.

The problem is that, as the caller, you should not be making
decisions based on the state of the called object that result in
you then changing the state of the object. The logic you are
implementing is probably the called object's responsibility, not
yours. For you to make decisions outside the object violates its
encapsulation.
(http://www.pragmaticprogrammer.com/p...s/1998_05.html)

Asking an object about its state (and asking its type is doing exactly
that) in order to decide how to work with that object violates
encapsulation. Even with boost::any.
Dec 21 '06 #15

Gianni Mariani wrote:
andrewmcdonagh wrote:
...
>From Effective C++, by Scott Meyers :
"Anytime you find yourself writing code of the form "if the object is
of type T1,
then do something, but if it's of type T2, then do something else,"
slap yourself."

What about boost::any ?
I don't particularly feel that boost::any is usefull. About the only
use for it might be passing objects through void* and reinterpreted
types.

The ideas behind boost::any are useful though for implementing an
interface for any object that can respond to a given set of functions
but aren't related to each other.

Neither of these cases asks the object for any data about itself.

Dec 21 '06 #16

Daniel T. wrote:
Asking an object about its state (and asking its type is doing exactly
that) in order to decide how to work with that object violates
encapsulation.
It (and asking its type is doing exactly that - violates encapsulation)
is not true for pointer/reference to polymorphic type especially in
languages with strict type check, as C++. The cause of asking - to get
extended interface of derived via pointer to its base class. Most user
code must _not_ use cast to derived.

Dec 22 '06 #17
"Grizlyk" <gr******@yandex.ruwrote:
Daniel T. wrote:
Asking an object about its state (and asking its type is doing exactly
that) in order to decide how to work with that object violates
encapsulation.

It (and asking its type is doing exactly that - violates encapsulation)
is not true for pointer/reference to polymorphic type especially in
languages with strict type check, as C++. The cause of asking - to get
extended interface of derived via pointer to its base class. Most user
code must _not_ use cast to derived.
I'm not sure what you are saying here, I will simply say it in code:

void foo( Type& t ) {
SubType* s = dynamic_cast<SubType*>( &t );
if ( s != NULL )
s->callFunc();
}

is no different logically than:

void foo( Type& t ) {
if ( t.isSub() )
t.callFunc();
}

In both cases, you are asking the object about its state, and then
deciding what to do with the object based on the value returned.
Dec 22 '06 #18
Daniel T. wrote:
>...to get extended interface of derived via pointer
to its base class

I'm not sure what you are saying here, I will simply say it in code:

void foo( Type& t ) {
SubType* s = dynamic_cast<SubType*>( &t );
if ( s != NULL )
s->callFunc();
}

is no different logically than:

void foo( Type& t ) {
if ( t.isSub() )
t.callFunc();
}
What if the function "callFunc()" is only defined
in the derived class? You need a pointer to the
derived class in order to call it.
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Dec 22 '06 #19

"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@n67g2000cwd.googlegr oups.com...
>
ms****@gmail.com wrote:
>Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

I am of the opinion that you should disable all possible language
features you can and rewrite them all yourself. Disable RTTI, disable
exceptions, and don't dare use the standard library...especially not
the STL.
You're being facetious.

Tony
Dec 22 '06 #20

Daniel T. wrote:
>"Grizlyk" wrote:
The cause of asking - to get
extended interface of derived via pointer to its base class. Most user
code must _not_ use cast to derived.
I'm not sure what you are saying here
// *** library module

//object
struct Base{ vritual void method()=0; };

//Most parts of user code
struct User
{
virtual void user1(Base& obj){ obj.method(); }
virtual void user2(Base& obj){ obj.method(); }
};

struct Creator
{
virtual Base* create_base()=0;
virtual User* create_user()=0;
};

// *** user module

struct userBase: public Base { void adjust(adjust_list); void method();
};

struct userUser: public User
{
//to get extended interface of derived via pointer to its base class
void user2(Base& obj)
{
userBase *const tmp=dynamic_cast<userBase*>(&obj)
if(!tmp){ obj.method(); return; }

tmp->adjust(adjust_list1);
obj.method();

tmp->adjust(adjust_list2);
obj.method();
}
};

struct userCreator: public Creator
{
Base* create_base(){ return new userBase;}
User* create_user(){ return new userUser;}
};

// *** another user module

extern Creator& extCreator();

//Most parts of user code
int main()
{
Base &base=extCreator().create_base();
User &user= extCreator().create_user();
...
user.user1(base);
...
{
userBase tmp
tmp.adjust(adjust_list3);
user.user1(tmp);
}
...
user.user2(base);
}

It is due to creator and user are not the solid object and they are
communicating each other via pointer to base class.

Dec 22 '06 #21

Tony wrote:
"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@n67g2000cwd.googlegr oups.com...

ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...
I am of the opinion that you should disable all possible language
features you can and rewrite them all yourself. Disable RTTI, disable
exceptions, and don't dare use the standard library...especially not
the STL.

You're being facetious.
And you're being redundant ;)

Dec 22 '06 #22
On 21 Dec 2006 01:28:27 -0800, Craig Scott <au**********@gmail.comwrote:
>

On Dec 21, 2:53 pm, "Grizlyk" <grizl...@yandex.ruwrote:
>Craig Scott wrote:
If two objects of the same type are created in different
modules/DLLs/shared libraries, then it is entirely possible that the
application will see them as two distinct types with different RTTI
id's.
It is not C++ bug. It is compiler bug, it is evidently. RTTI means
"type identification", not RTMI "module identification". If you are
using constant class description (for example, read-only header file
without preprocessor) in each module, any may expect equal runtime
class.

The C++ standard does not guarantee this (which is my point). In
practical reality, since everyone intuitively expects it, compiler
writers generally try to support it.
C. Scott argues (I think) that since the standard doesn't mention dynamic
linking, it should work like normal (static) linking.

You seem to argue that since the standard doesn't mention dynamic linking,
all bets are off.

Seems to me that this is the compiler/OS vendor's problem. They have to
state "our dynamic linking scheme is broken WRT C++, if you look at it as a
special case of linking".

/Jorgen

--
// Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
\X/ snipabacken.dyndns.org R'lyeh wgah'nagl fhtagn!
Dec 22 '06 #23

ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}

class B : public A { ... }

and now if I want to know what type of class it is I just call a
GetType method.

I'd be really pleased with any advice. Thanks.
There are a couple answers, mostly what other people have said. I'll
just mention them to contrast what I'm going to say:
1. Your design is potentially faulty -- this is applicable in either
case
2. If you KNOW you have a fixed set of types, this can work okay --
but it's increased maintanence
3. So if you must use this design, RTTI is usually better

I'll just mention an interesting case where this doesn't necessarily
apply: generated code. If your class heirarchy is generated, then
maintenance isn't an issue, and an approach similar to this can have a
couple useful benefits.

I'm working with a C++ front end now where the classes that represent
nodes of the abstract syntax tree (AST) are generated from a compact
description like the following (abbreviated):

class Statement {
-S_if;
-S_for;
-S_while;
}:

This would get expanded to:

class Statement { ... };
class S_if : public Statement { ... };
class S_for : public Statement { ... };
class S_while : public Statement { ... };

(In reality, the AST language allows you to specify data and function
members, but I'm leaving them out for simplicity.)

But it also generates essentially what you name. Statement contains:
enum Kind { S_IF, S_FOR, S_WHILE, NUM_KINDS }:
virtual Kind kind() const = 0;

Now this already has an unexpected benefit: while debugging in GDB, if
you have a Statement object s, you can see what kind it is by saying
"print s->kind()". I'm no GDB expert, but I don't know a way to do this
in general.

But there's more. It also generates more functions in Statement:
bool isS_if() const;
S_if* asS_if() const;
S_if* isS_if() const;

The former acts as you'd expect. The last acts exactly as dynamic_cast,
though I would guess faster. The second contains an assert(isS_if())
before returning. (There are also const versions of all of these.)

So depending on what you're doing, you have a syntactically cleaner way
of getting the downcast pointer than dynamic_cast.

This arose because the author was working in C++ before stuff was
standardized (let alone reliably implemented in compilers), though I
think he still prefers to use it, probably because of the cleaner
syntax.

Again, this is really only a good idea if you have auto-generated code.
In this example, the entire AST heirarchy comes out of the AST language
specs, so this isn't an issue.

-----
But this is a good place to ask this question, still working off of the
above. So I've got an AST, and I have classes that implement a visitor
interface that works like the GoF visitor. Except that my visitor only
has functions of the form like visitStatement, visitExpression, etc.
rather than visitS_if(), visitS_for(), visitE_funCall(), etc. This
means that my visit statement is more or less a "switch(s->kind()) case
S_IF: ..." type of thing.

I know the typical way that you're supposed to refactor this sort of
design smell (type tags) is by changing it to virtual methods. In this
case, there is a virtual function (e.g.) Statement::traverse(Visitor&)
each subclass implements to visit its children. (So
S_if::traverse(Visitor& vis) calls vis->visitStatement(this) then calls
traverse on the statements representing the branches.) I could see
changing this to call, say, visitS_if() instead of visitStatement().

However, suppose I can't do this. (As is pretty much the case;
implementing this would require changing the astgen program, and I
don't want to get into its internals.) Are there any better designs
that jump out?

In this case (again because the list of classes is very static) I don't
think that this is a big deal, and it's only mildly ugly, and I can't
come up with anything better, but it still smells a bit.

Evan

Dec 22 '06 #24

Evan wrote:
There are a couple answers, mostly what other people have said. I'll
just mention them to contrast what I'm going to say:
1. Your design is potentially faulty -- this is applicable in either
case
2. If you KNOW you have a fixed set of types, this can work okay --
but it's increased maintanence
3. So if you must use this design, RTTI is usually better

I'll just mention an interesting case where this doesn't necessarily
apply: generated code. If your class heirarchy is generated, then
maintenance isn't an issue, and an approach similar to this can have a
couple useful benefits.
Reading over this again, I think I was a little unclear. My example has
the same design smells as always; autogenerated code doesn't make that
go away. What I meant by "this" in "this doesn't necessarily apply" is
the problem with type tags where you have to modify the original class
when you add a new subclass. This is where the maintenance problem with
that approach comes up as compared to dynamic_cast.

BOTH approaches could probably be improved with virtual methods.

(BTW, I also realized after I posted that this sort of type tag
switching in my example is essentially a replacement for not being able
to do virtual dispatch on the type of an object passed as an argument
rather than this.)

Evan

Dec 22 '06 #25
ms****@gmail.com wrote:
I see another way of doing it...

class A {
public:
~virtual A() {}

enum Type { X, Y, Z };

Type GetType() { return type_; }

private:
Type type_;
}
That's basically what RTTI does, except the compiler
does it for you so it's neater, more reliable, smaller
(the variable "type_" isn't needed).

If you start taking out everything which you think is
only "syntactic sugar" then you'll end up with assembly
language.

Virtual functions can also be emulated via pointers,
why not get rid of them...?

If we follow this line of though to its conclusion we
end up with assembly language (or even hex keypunches
if you're an old dog of a programmer).
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Dec 22 '06 #26
"Grizlyk" <gr******@yandex.ruwrote:
Daniel T. wrote:
"Grizlyk" wrote:
>
The cause of asking - to get
extended interface of derived via pointer to its base class. Most user
code must _not_ use cast to derived.
I'm not sure what you are saying here
Your code has a poor design. If the userUser class can only work with
userBase objects, then define it as such. If it can work with all Base
objects, then it shouldn't need to dynamic_cast the Base object it has.
Dec 22 '06 #27
fungus <um*****@SOCKSartlum.comwrote:
Daniel T. wrote:
...to get extended interface of derived via pointer
to its base class

void foo( Type& t ) {
SubType* s = dynamic_cast<SubType*>( &t );
if ( s != NULL )
s->callFunc();
}

What if the function "callFunc()" is only defined in the derived
class? You need a pointer to the derived class in order to call it.
If 'callFunc()' is only defined in the base class and 'foo' needs to
call it to do its job, then 'foo' needs to be passed a 'SubType&'
instead of a 'Type&'. If 'foo' doesn't need to call 'callFunc()' to get
its job done, then it shouldn't call it.
Dec 22 '06 #28

"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@42g2000cwt.googlegro ups.com...
>
Tony wrote:
>"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@n67g2000cwd.googleg roups.com...
>
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...

I am of the opinion that you should disable all possible language
features you can and rewrite them all yourself. Disable RTTI, disable
exceptions, and don't dare use the standard library...especially not
the STL.

You're being facetious.

And you're being redundant ;)
I was just checking because I know someone else who has the same strategy.
Dec 23 '06 #29
Daniel T. wrote:
If the userUser class can only work with userBase objects,
then define it as such.
For the first, userUser class can work not only with userBase
> userBase *const tmp=dynamic_cast<userBase*>(&obj)
if(!tmp){ obj.method(); return; }
it can work with any Base.

For the second, I am not shure what have you offered as "define it as
such".
Can you make concrete improvements to my code example?

Bt the way, answer to the topic question is "yes, if you want to use
dynamic_cast, typeid and exception".

Dec 26 '06 #30

"fungus" <um*****@SOCKSartlum.comwrote in message
news:ky**************@news.ono.com...
ms****@gmail.com wrote:
That's basically what RTTI does, except the compiler
does it for you so it's neater, more reliable, smaller
(the variable "type_" isn't needed).

If you start taking out everything which you think is
only "syntactic sugar" then you'll end up with assembly
language.

Virtual functions can also be emulated via pointers,
why not get rid of them...?
Because they are not hard-to-implement-in-the-compiler-things
that only those with billion dollar budgets can do? All compiler
machinery is not equal.

Tony
Dec 26 '06 #31
"Grizlyk" <gr******@yandex.ruwrote:
>
Can you make concrete improvements to my code example?
An attempt to compile your 63 line (including comments) sample produces
19 errors and 2 warnings. With that kind of error rate, I'm not even
going to pretend to know what you think the code was supposed to
accomplish. As such I can suggest no improvements.

As to the appropriateness of down-casting, I suggest such a discussion
is unsuitable for comp.lang.c++ and should be moved over to comp.object
instead. IMHO, if you simply cannot find any other solution to the
problem, then by all means down-cast, but there is likely a much more
elegant solution hiding there somewhere.
Dec 26 '06 #32

Ron Natalie wrote:
ms****@gmail.com wrote:
Well I've got a problem, that is more theoretical than practital. I
need to know benefits of RTTI. I see another way of doing it...
Actually, it's probably a defect in your design if you EVER
have to ask what an object is. If there is behavior that
is dependent on the type of an object, it probably should be
implemented in a virtual method of the class.
That assumes that you had perfect foresight when you designed the
class.
In practise beware of theoretical dogma and use dynamic_cast if its
useful.

Use of dynamic cast is non intrusive.
This means that you can add functionality without disturbing previous
code.

You can look at dynamic cast as a query as to whether an object
provides a particular interface. For example:
#include <iostream>

struct object{
virtual ~object(){}
virtual const char* id() const = 0;
};
// old code
struct line : object{const char* id() const{return "line";}};
struct circle : object{ const char* id() const{return "circle";}};

// new code

struct colour{};
struct colourable{
virtual ~colourable(){}
virtual void set_colour( colour )=0;
};

colourable* as_colourable( object * p)
{
return dynamic_cast<colourable*>(p);
}
bool is_colourable(object* p)
{
return as_colourable(p) !=0;
}

struct filleable : colourable{
virtual ~filleable(){}
bool fill(){return m_fill;}
virtual void set_fill( colour )=0;
private:
bool m_fill;
};
filleable * as_filleable(object * p)
{
return dynamic_cast<filleable*>(p);
}
bool is_filleable(object * p)
{
return as_filleable(p) !=0;
}

struct line_v2 : line , colourable {
void set_colour( colour ){}
};
struct circle_v2 : circle , filleable{
void set_colour( colour ){}
void set_fill( colour ){}
};

void enable_menu_item(std::string const & str, bool value){}
object * get_selected(){return 0;}
void pre_menu_popup()
{
object * p = get_selected();
// new functionality
enable_menu_item("set colour",is_colourable(p) && !is_filleable(p));
enable_menu_item("set fill colour", is_filleable(p) &&
as_filleable(p)->fill());
enable_menu_item("set outline colour ", is_filleable(p) );
}

void get_item_interfaces(object * p)
{
std::cout << p->id() << ' '<< (is_colourable(p)? "is":"is not") << "
colourable\n";
std::cout << p->id() << ' '<< (is_filleable(p)? "is":"is not") << "
filleablle\n";
}
int main()
{
line l1;
circle c1;
line_v2 l2;
circle_v2 c2;
get_item_interfaces(&l1);
get_item_interfaces(&c1);
get_item_interfaces(&l2);
get_item_interfaces(&c2);

}

Dec 26 '06 #33

Daniel T. wrote:
>"Grizlyk" <gr******@yandex.ruwrote:
Can you make concrete improvements to my code example?

An attempt to compile your 63 line (including comments) sample produces
19 errors and 2 warnings. With that kind of error rate, I'm not even
going to pretend to know what you think the code was supposed to
accomplish. As such I can suggest no improvements.

I suggest such a discussion is unsuitable for comp.lang.c++
and should be moved over to comp.object instead.
Ok. To descrease error rate any can remove or comment "..." in
function's bodys, define parameter macros and so on. But I do it, and
post it to comp.object as "avoid cast to derived"
http://groups.google.com/group/comp....93804b2c7b74c3

Dec 27 '06 #34

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Rick | last post by:
Hi, I wrote a few classes recently and am writing a small GC implementation for C++. I will be implementing my own gc_ptr type maintain a list where I'll store pointers to allocated memory. I...
2
by: shishir | last post by:
Please consider the following //file test.cpp #include <iostream> int main() { int x; try { throw x;
6
by: Kleidemos | last post by:
If I implement a simple RTTI system, more simple than C++ RTTI system for my program and this system is plus or minus: #define DEF_RTTI_BASE(name) virtual inline const char *Name(){ return...
9
by: Agoston Bejo | last post by:
Hello there, I would like to know what overheads there are to think of when using RTTI. I understand that enabling RTTI increases the sizes of the classes, but not the objects themselves. This...
2
by: denny | last post by:
Hey all, I know that dynamic_cast<> takes some time, but , for instance, is there a memoy cost associated in with it? Does it have to maintain a table in memory, thus bloating the runtime ram...
3
by: Steven T. Hatton | last post by:
I'm trying to work out a design for dynamically determining file types, and for generating new files of a given type. I'm curious to know what others think of my current strategy. Is it "so...
10
by: Neo | last post by:
what is RTTI? and how to implements it? give me sourceful link for learn and implements it (using standard C mean portable). regards, -aims
5
by: dotNeter | last post by:
I'm studying the RTTI, and my current work is concern for how to get the self-defined type at runtime, that's exactly what the RTTI does. I mean, in my application, I built several self-defined...
2
by: Chameleon | last post by:
I know than dynamic_cast check string name of derived to base class and if one of them match, return the pointer of that object or else zero. I suppose, I dynamic_cast instead of strings, checks...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.