Kotaka Danski
Kotaka Danski

Reputation: 600

How to compare two objects by class name or type (equivalent of Java's `getClass()` in C++)

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

Answers (2)

Detonar
Detonar

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

Caleth
Caleth

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

Related Questions