Отмена преобразования для системы компонентов

В настоящее время я работаю над игровым движком на основе компонентов, написанным на С++. Все компоненты наследуются от базового класса компонента. Все компоненты в сцене преобразуются в вектор компонентов, где их можно повторять и Update(), и их можно вызывать.

Я пытаюсь придумать систему связи для компонентов. Если у меня есть функция с именем GetComponent<Type>() Like Unity, я смогу вернуть компонент из того, что было до того, как он был преобразован.

Итак, в основном у меня есть компонент с улучшенным преобразованием, и я хочу изменить его, чтобы он был его исходным классом, а затем вернуть его через функцию (как класс, которым он был раньше). Это возможно? Если бы это было возможно, как компонент узнал бы, каким классом он был раньше?

Есть ли какие-либо примеры этого, на которых я могу учиться?


person DavidColson    schedule 21.08.2012    source источник
comment
Это невозможно с вектором Компонентов. Используйте вектор *Components или shared_ptr‹Components›.   -  person Henrik    schedule 21.08.2012
comment
Извините, забыл упомянуть, что это вектор указателей   -  person DavidColson    schedule 21.08.2012


Ответы (3)


Чтобы это работало, вам нужно знать исходный тип компонента, каким он был, прежде чем добавлять его в коллекцию (преобразовывать его).

Итак, зная это, это можно сделать так (при условии, что component имеет тип Component*):

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

Не то, чтобы dynamic_cast мог выйти из строя => вышеприведенное может установить specific в nullptr, если фактический тип компонента не применим. Это, а также тот факт, что оно медленнее, чем другие приведения, делает его наиболее нелюбимым из приведений C++.

Вы также можете взглянуть на boost::polymorphic_downcast, который похож по функциям. Он делает dynamic_cast и утверждает, если он терпит неудачу в режиме DEBUG, но делает более быстрый static_cast в режиме RELEASE.

person Lyubomir Vasilev    schedule 21.08.2012

Я предполагаю, что под повышением приведения компонента вы подразумеваете приведение указателя (или ссылки) на него к указателю на базовый класс. В этом случае используйте dynamic_cast<Derived *>(pointer) (или dynamic_cast<Derived &>(reference) для безопасного приведения вниз во время выполнения.

person Grzegorz Herman    schedule 21.08.2012

Если у вас есть RTTI, это можно сделать довольно легко. Я предлагаю иметь 2 функции 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;
}

Вот как это выглядит в моем движке: у меня есть индекс, который по умолчанию равен 0, чтобы позволить мне перебирать все экземпляры, поскольку у меня может быть более одного экземпляра определенного компонента.

person Ylisar    schedule 21.08.2012