Reputation: 107
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
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
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
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.
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