How do I compare class types in C ++?

Let's say I have:

class Base {/*...*/}
class Derived1: public Base {/*...*/}
class Derived2: public Base {/*...*/}

      

.. and I have:

class SomeClass {
public:
    template<typename DerivedType>
    DerivedType GetDerived();
private:
    vector<Base*> m_classes;
}

      

In the function, GetDerived()

I iterate over the vector m_classes and want to do something like:

if(m_classes[i] == DerivedType) {
    return m_classes[i];
}

      

... and suppose we know that one of the objects in m_classes will contain a DerivedType object.

Example:

m_classes[2] = Base* BasePtr = new Derived1;

      

.. in this case I would like to use the GetDerived function like this:

GetDerived<Derived1>();

      

.. and this should return m_classes [2]

How should I do it? How do I compare a base pointer object with a derived class type? More precisely, what should the function look like GetDerived()

?

+3


source to share


5 answers


Storing objects of different classes in the same container when you need to treat them differently is a bad idea.

This time, C ++ has what you are looking for. dynamic_cast<B>(a)

will try to convert a

(whatever it is) for input B

. If the execution classes don't match, it will return nullptr

.

This is how you could write GetDerived

:

template <class Tsearched>
Tsearched *GetDerived() {
    for(auto c : m_classes) {
        if(Tsearched *ptr = dynamic_cast<Tsearched*>(c))
            return ptr;
    }
    return nullptr;
}

      



Or, using the standard algorithm:

template <class Tsearched>
Tsearched *GetDerived() {
    auto found = std::find_if(m_classes.begin(), m_classes.end(), [](Base *ptr) {
        return dynamic_cast<Tsearched*>(ptr);
    });
    return found == m_classes.end() ? nullptr : static_cast<Tsearched*>(*found);
}

      

Let me repeat, however, that there is a design issue here. RTTI (what it uses dynamic_cast

) is neither elegant nor fast.

+1


source


You can use dynamic_cast<>

:

template<typename DerivedType>
std::vector<DerivedType*> GetDerived() { // note: return type changed
 std::vector<DerivedType*> result;
 for (DerivedType* at : this->m_classes) {
  if (DerivedType* as = dynamic_cast<DerivedType*>(at)) {
   result.push_back(as);
  }
 }
 return result;
}

      



dynamic_cast<>

a type Base

with runtime type information is required (which will exist for types that have virtual functions).

It's worth noting that some people don't like dynamic_cast<>

it and some conventions / codebases prohibit it. It is a tool and can be misused.

+2


source


It's usually not good to do this kind of thing.

You can use dynamic_cast

which returns nullptr

if the object is not of this type and a pointer to that type otherwise:

if (nullptr != dynamic_cast<DerivedType*>(m_classes[i])) 
{ ... }

      

+1


source


As other people have said, you should see if this is indeed the best way to attack your problem, but dynamic_cast

available in C ++. You must use Runtime Type Identification or RTTI.

Once you've enabled it in your compiler options, you can do this in your loop:

DerivedType* maybeDerived = dynamic_cast<DerivedType>(m_classes[i]);
if (maybeDerived)
     return maybeDerived;

      

+1


source


Your example is not valid syntax. You have no announcement in the middle of the assignment. However, something like http://en.cppreference.com/w/cpp/types/is_base_of can help identify derivations at compile time. As far as defining derived types at runtime is concerned, you can use dynamic_cast

, however ideal solutions do not need to do this, and this often means that there is a potential design error in your objects or a way of using them.

As @PaulMcKenzie pointed out, you should probably be asking yourself, "Why?" before you worry about how.

0


source







All Articles