Should I use RTTI?

Discussion in 'C++' started by mscava@gmail.com, Dec 20, 2006.

  1. Guest

    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, 2006
    #1
    1. Advertising

  2. Ian Collins Guest

    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.
    Ian Collins, Dec 20, 2006
    #2
    1. Advertising

  3. Ian Collins Guest

    Ian Collins wrote:
    > 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.
    Ian Collins, Dec 20, 2006
    #3
  4. 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" ?
    Gianni Mariani, Dec 20, 2006
    #4
  5. Salt_Peter Guest

    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.
    Salt_Peter, Dec 20, 2006
    #5
  6. Noah Roberts Guest

    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.
    Noah Roberts, Dec 20, 2006
    #6
  7. Grizlyk Guest

    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<>.
    Grizlyk, Dec 21, 2006
    #7
  8. Craig Scott Guest

    On Dec 21, 4:54 am, 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/comp.lang.c /browse_frm/thread/0b4577aff1feaa6e/?hl=en#

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

    --
    Computational Fluid Dynamics, CSIRO (CMIS)
    Melbourne, Australia
    Craig Scott, Dec 21, 2006
    #8
  9. Grizlyk Guest

    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
    Grizlyk, Dec 21, 2006
    #9
  10. Daniel T. Guest

    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.
    Daniel T., Dec 21, 2006
    #10
  11. Craig Scott Guest

    On Dec 21, 2:53 pm, "Grizlyk" <> wrote:
    > 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
    Craig Scott, Dec 21, 2006
    #11
  12. Ron Natalie Guest

    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.
    Ron Natalie, Dec 21, 2006
    #12
  13. On Dec 21, 3:23 pm, Ron Natalie <> wrote:
    > 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."
    andrewmcdonagh, Dec 21, 2006
    #13
  14. 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 ?
    Gianni Mariani, Dec 21, 2006
    #14
  15. Daniel T. Guest

    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 ?


    ... 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/ppllc/papers/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.
    Daniel T., Dec 21, 2006
    #15
  16. Noah Roberts Guest

    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.
    Noah Roberts, Dec 21, 2006
    #16
  17. Grizlyk Guest

    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.
    Grizlyk, Dec 22, 2006
    #17
  18. Daniel T. Guest

    "Grizlyk" <> wrote:
    > 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.
    Daniel T., Dec 22, 2006
    #18
  19. fungus Guest

    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.
    fungus, Dec 22, 2006
    #19
  20. Tony Guest

    "Noah Roberts" <> wrote in message
    news:...
    >
    > 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
    Tony, Dec 22, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Harrison

    Re: RTTI

    John Harrison, Jul 14, 2003, in forum: C++
    Replies:
    2
    Views:
    448
    John Harrison
    Jul 14, 2003
  2. Alf P. Steinbach

    Re: RTTI

    Alf P. Steinbach, Jul 14, 2003, in forum: C++
    Replies:
    0
    Views:
    463
    Alf P. Steinbach
    Jul 14, 2003
  3. Steven Lien

    About RTTI

    Steven Lien, Aug 19, 2003, in forum: C++
    Replies:
    4
    Views:
    594
    Ivan Vecerina
    Aug 19, 2003
  4. BillyO
    Replies:
    2
    Views:
    486
    dslater
    Sep 30, 2003
  5. tirath
    Replies:
    3
    Views:
    706
    Ivan Vecerina
    Oct 12, 2003
Loading...

Share This Page