Question

I am currently working on a Component based game engine written in c++. All components inherit from a component base class. All components in the scene are upcasted into a vector of Components were they can be iterated over and Update() and such can be called.

I am trying to come up with a communication system for the components. If I have a function called GetComponent<Type>() Like Unity will I be able to return a component from what is used to be before it was upcasted.

So basically i have an upcasted component and I want to reverse it so it is its original class and then return it via the function(as the class it used to be). Is this possible? If it were possible how would the component know what class it used to be?

Are there any examples of doing this I can learn from?

Was it helpful?

Solution

For this to work you would have to know the original type of the component as it was before adding it to the collection (upcasting it).

So knowing that, it can be done like this (assuming component is of type Component*):

SpecificComponent* specific = dynamic_cast<SpecificComponent*>(component);

Not that dynamic_cast can fail => the above can set specific to nullptr if the actual component type is not applicable. That, and the fact that it is slower than the other casts make it the most disliked of the C++ casts.

You can also take a look at boost::polymorphic_downcast, which is similar in function. It makes a dynamic_cast and asserts if it fails in DEBUG mode, but does the faster static_cast in RELEASE mode.

OTHER TIPS

I assume that by upcasting a component, you mean casting a pointer (or reference) to it to a pointer to the base class. In this case, use dynamic_cast<Derived *>(pointer) (or dynamic_cast<Derived &>(reference) to do a safe down-cast at runtime.

If you have RTTI it's possible to do the mapping rather easily. I suggest having 2 functions GetComponentExact & GetComponentDerived.

template< typename Type >
Type* GameObject::FindComponentExact( size_t a_Index )
{
    size_t found = 0;
    for( ComponentVector::iterator itrCur = m_Components.begin(), itrEnd = m_Components.end(); itrCur != itrEnd; ++itrCur )
        if( typeid( Type ) == typeid( *(*itrCur) ) && found++ == a_Index )
            return static_cast< Type* >( *itrCur );
    return NULL;
}

template< typename Type >
Type* GameObject::FindComponentDerived( size_t a_Index )
{
    size_t found = 0;
    for( ComponentVector::iterator itrCur = m_Components.begin(), itrEnd = m_Components.end(); itrCur != itrEnd; ++itrCur )
        if( dynamic_cast< Type* >( *itrCur ) && found++ == a_Index )
            return static_cast< Type* >( *itrCur );
    return NULL;
}

This is how it looks like in my engine, I have an index which I default to 0 to let me iterate over all instances since I can have more than a single instance of a particular component.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top