Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++ check if two instances of a base class are infact of the same subclass

The below code explains the problem. Fill in same_sub_class to detect if the two pointers to virtual base class A are in fact the same concrete class.

struct A {
    ...
}:

struct B : public A {
    ...
}:

struct C : public A {
    ...
}


bool same_sub_class(A * a1, A * a2){
    // Fill this in to return true if a1 and a2 are
    // of the same concrete class
}

EDIT:

As I look at my application I need something slightly different from the above. I need to be able to group instances by their type_id.

FYI. I have a mini symbolic algerbra system so to do manipulations it is important to know the class type sometimes for sorting, and rearranging expressions.

So given a vector of pointers to instance how to group them by their type_id. I'd either need to be able to hash the type_id or generate a unique integer for every class.

like image 803
bradgonesurfing Avatar asked Oct 05 '10 12:10

bradgonesurfing


4 Answers

If you can use RTTI,

typeid(*a1) == typeid(*a2)

I think you also need to

#include <typeinfo>

And you must have a virtual function in your classes so that the vtable exists--a destructor should do fine.

UPDATE:

I'm not sure I completely understand what your requirements are for grouping (Do you need some kind of deterministic ordering? What should happen with sub-subclasses?), but you could try using the value returned from the typeid operator to either:

  • Hash the string returned from typeid(*ptr).name()
  • Use typeid(*a1).before(typeid(*a2)) as an ordering criterion. This doesn't have any determinism between runs, though.

Generally when considering RTTI, it is a good idea to see if any of this can be accomplished better using well-crafted virtual functions (double dispatch, for example). I really can't say if there is a good alternative in your case though, since I don't understand the specifics.

like image 112
Tim Yates Avatar answered Nov 18 '22 00:11

Tim Yates


Actually there are a fairly simple answers to this. But it involves posing the questions a bit clearer.

(A) If I want to store typeinfo objects in an unordered_set what do I need to do?

typeinfo support the == and the name() method. The name can be used to generate a hash and == for equality

(B) If I want to store typeinfo objects in an ordered_set ( std::set ) what do I need to do?

typeinfo supports the == and the before() method. With bit of wrapping of these two methods I can implement an interface for a Compare function that gives me strict weak ordering.

like image 26
bradgonesurfing Avatar answered Nov 17 '22 23:11

bradgonesurfing


typeid(*a1) == typeid(*a2)

Note the dereference, it is important.

like image 9
usta Avatar answered Nov 18 '22 00:11

usta


You could make your own type Identifier:

struct A{
...
protected:
 enum TypeTag{B_TYPE, C_TYPE};
 TypeTag typeTag;
};

And then in constructors of subclasses:

B::B()
: typeTag(TypeTag::B_TYPE)
{
...
}

C::C()
: typeTag(TypeTag::C_TYPE)
{
...
}
like image 2
Adesit Avatar answered Nov 17 '22 23:11

Adesit