UmBottesWillen
UmBottesWillen

Reputation: 107

Simple method of testing what class an object is of?

I am creating objects of 3 classes that all inherit from 1 superclass and then store them in a vector<superclass*>. Now I want to iterate over all objects of one particular class, but I fail to discern between the 3 classes.

I tried typeid(), but that only returns the superclass. I decided against using dynamic_cast<class>(), as I read that it was something to be avoided if possible. All I want to know is what class I'm dealing with when picking an object from the vector.

Is there something simple like .getClass().IsInstance() in Java that I could use?

Upvotes: 0

Views: 80

Answers (3)

eerorika
eerorika

Reputation: 238351

Simple method of testing what class an object is of?

There is decltype which gives you the static type of an expression. You seem to want the dynamic type, so this is not useful to your case.

You can test whether a reference / pointer points to an object of particular subclass using dynamic_cast. If the result of the cast is null, then the pointed object is not of the target type.

Furthermore, there is typeid operator, which will return a std::type_info object representing the dynamic type of the object.

Note that typeid and dynamic_cast only work with the dynamic type if the base class is polymorphic. This means that the class must have at least one virtual member function.

I have to count the number of instances of each of the 3 classes

typeid seems like a good choice for this use case. You can for example produce an unordered map from std::type_info to number of objects.

Upvotes: 0

Ketzu
Ketzu

Reputation: 691

Yes there is, it is called Run Time Type Information (RTTI) but be aware that it might not be good design to use it in the way you intent to.

If you need to distinguish objects like that, you should consider they might need separate handling (different vectors), should not be related classes or similar.

Other options to distinguish: Add a method returning a type identifier (make an enum).

Also be aware that a vector of superclass objects does not exhibit late binding behvaiour (e.g. calling of the subclass method).

The example below encapsulates the typeinfo and the problem with a vector of objects:

#include <iostream>
#include <typeinfo>
#include <vector>

class A {
    public:
    virtual int getInt() {return 2;}
};

class B : public A {
    public:
    virtual int getInt() {return 5;}
};

class C : public A {
    public:
    virtual int getInt() {return 3;}
};

int main()
{
  std::vector<A> v;
  v.push_back(A());
  v.push_back(B());
  v.push_back(C());

  for(auto &e:v) {

      std::cout << typeid(e).name() << " -> ";
      std::cout << e.getInt() << std::endl;
  }
}

The output in my trial run is:

1A -> 2 
1A -> 2 
1A -> 2

Upvotes: 0

Alecto
Alecto

Reputation: 10740

The fastest way to do this is to add a method to the superclass which returns something that represents the type of the child:

class MyBase {
   public:
    enum type { Base, DerivedA, DerivedB, DerivedC }; 

    virtual type getType() const {
        return Base; 
    }
    virtual ~MyBase() {}
};

Then, you'll overload this method in each child class:

class MyDerivedA : public MyBase {
   pubilc:
    MyBase::type getType() const override {
        return MyBase::type::DerivedA;
    }
};
class MyDerivedB : public MyBase {
   pubilc:
    MyBase::type getType() const override {
        return MyBase::type::DerivedB;
    }
};
class MyDerivedC : public MyBase {
   pubilc:
    MyBase::type getType() const override {
        return MyBase::type::DerivedC;
    }
};

This method is a little tedious, but it'll work fine. That being said, this brings us to the big issue.

Why is using dynamic_cast discouraged?

From a technical standpoint, there is nothing wrong with dynamic_cast. Use it when you need it. In this particular case, there's a good chance you need it.

However, having to figure out the specific derived type of a class oftentimes indicates a design flaw. Having inheritance and virtual methods is supposed to eliminate the need to know the derived type.

That's why dynamic_cast is discouraged.

Upvotes: 1

Related Questions