0

Given that there are the following struct types:

struct A {};
struct B : A {};
struct C : A {};
struct D : B {};

And we have a piece of code:

A a = f();

How would you check what type the struct actually is? i.e. is it A, B, C or D?

I can give the context in which I'm trying to use the answer for this if needed, but I don't think that's needed.

Bertie Wheen
  • 1,215
  • 1
  • 13
  • 20
  • 1
    It probably is needed (how do we know a virtual function won't solve your problem) and the type is clearly `A`, always, since any derived type returned would be sliced. – chris Aug 11 '13 at 10:39

2 Answers2

2

Note that polimorphism in C++ only works with pointers and references, if you return A by value, it will always be an A. If the function f() returns a class of type B, slicing will occur.

If you change the function to return a pointer to A, then you can use a dynamic cast and check if returns null.

A *a=f();
B *b=dynamic_cast<B*>(a);
if(b!=NULL)
{
    //a was of type B
}
Community
  • 1
  • 1
user2671945
  • 315
  • 1
  • 6
  • My question was less regarding how we're obtaining `a`, more how do we check if it's actually something else (e.g. `B`). The `dynamic_cast` approach works. Thanks :) – Bertie Wheen Aug 11 '13 at 10:33
  • Keep in mind that if you happen to do the same with references instead of pointers, `dynamic_cast` throws an exception of type `bad_cast` if the type doesn't match (as null references don't exist in C++). – user2671945 Aug 11 '13 at 10:40
  • @user2671945 And sometimes, an exception is exactly what you need. :-) – C. K. Young Aug 11 '13 at 10:42
  • 1
    I wasn't implying anything negative with the exception behaviour. You just have to be aware of that, and remeber a `try..catch` block around a `dynamic_cast` among references when you're unsure if it'll succeed, just as the OP asked. – user2671945 Aug 11 '13 at 10:47
0

It's type A. Why? Because of slicing.

If, however, f() returned an A&, and you used A& a = f(); instead, then you have two options (both involving RTTI):

  1. You could use typeid(a) and either look at its name() or compare against the type_info objects for the various (sub)classes.

  2. You could use a dynamic_cast: for example, dynamic_cast<D*>(&a) would return null if a is not of type D.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435