tags:

views:

128

answers:

2

My question is related to RTTI in C++ where I'm trying to check if an object belongs to the type hierarchy of another object. The BelongsTo() method checks this. I tried using typeid, but it throws an error and I'm not sure about any other way how I can find the target type to convert to at runtime.

#include <iostream>
#include <typeinfo>

class X
{
    public:
        //  Checks if the input type belongs to the type heirarchy of input object type
        bool BelongsTo(X* p_a)
        {
            //  I'm trying to check if the current (this) type belongs to the same type 
            //  hierarchy as the input type
            return dynamic_cast<typeid(*p_a)*>(this) != NULL;   //  error C2059: syntax error 'typeid'
        }
};

class A : public X
{
};

class B : public A
{
};

class C : public A
{
};

int main()
{
    X* a = new A();
    X* b = new B();
    X* c = new C();
    bool test1 = b->BelongsTo(a);   // should return true
    bool test2 = b->BelongsTo(c);   // should return false
    bool test3 = c->BelongsTo(a);   // should return true
}

Making the method virtual and letting derived classes do it seems like a bad idea as I have a lot of classes in the same type hierarchy. Or does anybody know of any other/better way to the do the same thing? Please suggest.

Update: b.BelongsTo(a) should detect if the input object type (a) is an ancestor of the current object (b) in the type hierarchy.

+2  A: 

In order for RTTI to work class X needs at least one virtual member function (virtual destructor counts as well). Without virtual member functions the class will not have a vtable generated by the compiler and so when you invoke typeid the latter will not work as you expect.

sharptooth
I added a virtual destructor in each class. But it still shows that syntax error. Any ideas?
Elroy
Yes, see Neil Butterworth's answer.
sharptooth
+2  A: 

This doesn't make sense - the very fact that you can call the function means that the parameter belongs to the X hierarchy, as that is the type of the parameter. Dynamic casts are intended to find out the actual type within a known hierarchy.

The syntax error in your code:

return dynamic_cast<typeid(*p_a)*>(this) != NULL;  

is because a typeid is not a type - you simply cannot use it as a type with dynamic_cast like that.

If as Naveen suggests you want to find out if an instance belongs to a sub-hierarchy, use:

if ( dynamic_cast <A*>( some_x_ptr ) ) {

    // yes, belongs to A sub-hierarchy
}

Edit: You have:

A <- P <- X
A <- Q <- Y

Then:

A * a = new X;

dynamic_cast <P *>( a );   // not null
dynamic_cast <Q *>( a );   // null
anon
Notice that `class B` and `class C` are derived from `class A`. I think the intention of OP is to find whether the passed objects belongs to this sub-hierarchy or not.
Naveen
I apologize for not making myself really clear here. For eg. X derives from P, Y derives from Q, where P and Q derive from A. So, X belongs to P and A, Y belongs to Q and A but X does not belong to Q. I need this behavior.
Elroy
I'm not sure if there's a name for this kind of detection but it looks like checking for ancestors.
Elroy
Awesome, now how do you think this fits into the code I have written. If you try that maybe you'll get a better picture of what I'm trying to do. What changes in BelongsTo() would be needed?
Elroy
@Elroy You can't write it as a normal function because the thing in the angle brackets must be known at compile time. You could write it as a template (I think).
anon
Okay. The best solution is then to make it virtual and provide implementation in all subclasses, right?
Elroy
@Elroy No, the best solution is simply to use dynamic_cast, which does exactly what you want.
anon
Okay. Thanks a lot.
Elroy