Reputation: 600
I'd like to compare two objects by their class name. The first object is of type Card*
which points to a MagicCard
object, and the second is of type MagicCard
- a child class of Card
. When I compare them with typeid
it doesn't work:
if (typeid(*(this->cards[index])) != typeid(card)) {
//the first object is of type Card* inside a vector and points to a
MagicCard object
//card is of type MagicCard
return false;
//this "if" check stops the method in case the types are different.
}
The comparison above should return that the objects are of the same type, because the the element in that position inside the vector I know that there is a function getClass()
in Java so I am looking for some kind of an equivalent in C++ which compares objects by the derived class, not by the mother class.
EDIT: I changed the code to Peter's suggestion and added information why I need this check. It doesn't work yet.
Upvotes: 0
Views: 947
Reputation: 1429
It is not clear how your Card
and MagicCard
classes are declared.
typeid
does not work with non-polimorphistic classes according to cppreference.com.
If you, for example got the following program, the output will be as shown in the comments next to the output line:
#include <iostream>
#include <typeinfo>
class BaseNonPoly { };
class DerivedNonPoly : public BaseNonPoly { };
class BasePoly { virtual void foo() {} };
class DerivedPoly : public BasePoly { };
int main()
{
BaseNonPoly baseNonPoly;
DerivedNonPoly derivedNonPoly;
BasePoly basePoly;
DerivedPoly derivedPoly;
BaseNonPoly& pBaseNonPoly = baseNonPoly;
BaseNonPoly& pDerivedNonPoly = derivedNonPoly;
BasePoly& pBasePoly = basePoly;
BasePoly& pDerivedPoly = derivedPoly;
std::cout << "typeid(baseNonPoly)=" << typeid(baseNonPoly).name() << std::endl; // typeid(baseNonPoly)=11BaseNonPoly
std::cout << "typeid(derivedNonPoly)=" << typeid(derivedNonPoly).name() << std::endl; // typeid(derivedNonPoly)=14DerivedNonPoly
std::cout << "typeid(basePoly)=" << typeid(basePoly).name() << std::endl; // typeid(basePoly)=8BasePoly
std::cout << "typeid(derivedPoly)=" << typeid(derivedPoly).name() << std::endl; // typeid(derivedPoly)=11DerivedPoly
std::cout << "typeid(pBaseNonPoly)=" << typeid(pBaseNonPoly).name() << std::endl; // typeid(pBaseNonPoly)=11BaseNonPoly
std::cout << "typeid(pDerivedNonPoly)=" << typeid(pDerivedNonPoly).name() << std::endl; // typeid(pDerivedNonPoly)=11BaseNonPoly
std::cout << "typeid(pBasePoly)=" << typeid(pBasePoly).name() << std::endl; // typeid(pBasePoly)=8BasePoly
std::cout << "typeid(pDerivedPoly)=" << typeid(pDerivedPoly).name() << std::endl; // typeid(pDerivedPoly)=11DerivedPoly
return 0;
}
As you can see, the object of the non-polimorphic derived class DerivedNonPoly
without virtual method can not be identified as what it really is and returns the type of it's parent BaseNonPoly
instead.
As in Caleth's answer mentioned, it is good practice to avoid special cases depending on concrete derived class types. Since this, however, can't always be avoided in an elegant way, it might be enough to use a unused virtual function or a virtual deconstructor to your Card
and MagicCard
class for typeid
to work correctly.
Upvotes: 1
Reputation: 62684
It's almost always incorrect to be looking at typeid
.
You can get a MagicCard *
from a Card *
with dynamic_cast
, and it will be a null pointer if the Card *
doesn't point to a MagicCard
object.
if (auto * magicCard = dynamic_cast<MagicCard>(cards[index])) {
// do something with magicCard
}
However it is often better to add virtual void doSomething()
to Card
, and override it in MagicCard
.
cards[index]->doSomething(); // no mention of MagicCard needed
Upvotes: 3